diff options
| author | Anton Blanchard <anton@samba.org> | 2002-09-11 15:53:48 +1000 |
|---|---|---|
| committer | Anton Blanchard <anton@samba.org> | 2002-09-11 15:53:48 +1000 |
| commit | 98398ebac81a1beb9342bec4fc36d6b9185249c0 (patch) | |
| tree | b79be2e9a19a1e1a70e5e797040a9fd558c009ea | |
| parent | 09b1ed32b4aefc85e11c1dbdd66569cf1276a59d (diff) | |
| parent | ed245b591594a32d5ca1ee7d1285fef1d51f14ba (diff) | |
Merge samba.org:/scratch/anton/linux-2.5
into samba.org:/scratch/anton/linux-2.5_bar
87 files changed, 3180 insertions, 7205 deletions
diff --git a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c index 78f89522b95a..e2d1ffb97f89 100644 --- a/arch/i386/kernel/acpi.c +++ b/arch/i386/kernel/acpi.c @@ -166,6 +166,7 @@ acpi_parse_lapic_addr_ovr ( return 0; } +#ifndef CONFIG_ACPI_HT_ONLY static int __init acpi_parse_lapic_nmi ( @@ -185,12 +186,16 @@ acpi_parse_lapic_nmi ( return 0; } +#endif /*CONFIG_ACPI_HT_ONLY*/ + #endif /*CONFIG_X86_LOCAL_APIC*/ #ifdef CONFIG_X86_IO_APIC int acpi_ioapic; +#ifndef CONFIG_ACPI_HT_ONLY + static int __init acpi_parse_ioapic ( acpi_table_entry_header *header) @@ -251,6 +256,7 @@ acpi_parse_nmi_src ( return 0; } +#endif /*!CONFIG_ACPI_HT_ONLY*/ #endif /*CONFIG_X86_IO_APIC*/ @@ -361,18 +367,21 @@ acpi_boot_init ( return result; } +#ifndef CONFIG_ACPI_HT_ONLY result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi); if (result < 0) { printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); /* TBD: Cleanup to allow fallback to MPS */ return result; } +#endif /*!CONFIG_ACPI_HT_ONLY*/ acpi_lapic = 1; #endif /*CONFIG_X86_LOCAL_APIC*/ #ifdef CONFIG_X86_IO_APIC +#ifndef CONFIG_ACPI_HT_ONLY /* * I/O APIC @@ -410,6 +419,7 @@ acpi_boot_init ( acpi_ioapic = 1; +#endif /*!CONFIG_ACPI_HT_ONLY*/ #endif /*CONFIG_X86_IO_APIC*/ #ifdef CONFIG_X86_LOCAL_APIC diff --git a/arch/i386/kernel/cpu/mtrr/cyrix.c b/arch/i386/kernel/cpu/mtrr/cyrix.c index ace423c0a83c..30e1d3aac5bc 100644 --- a/arch/i386/kernel/cpu/mtrr/cyrix.c +++ b/arch/i386/kernel/cpu/mtrr/cyrix.c @@ -110,12 +110,54 @@ cyrix_get_free_region(unsigned long base, unsigned long size) return -ENOSPC; } +static u32 cr4 = 0; +static u32 ccr3; + +static void prepare_set(void) +{ + u32 cr0; + + /* Save value of CR4 and clear Page Global Enable (bit 7) */ + if ( cpu_has_pge ) { + cr4 = read_cr4(); + write_cr4(cr4 & (unsigned char) ~(1 << 7)); + } + + /* Disable and flush caches. Note that wbinvd flushes the TLBs as + a side-effect */ + cr0 = read_cr0() | 0x40000000; + wbinvd(); + write_cr0(cr0); + wbinvd(); + + /* Cyrix ARRs - everything else were excluded at the top */ + ccr3 = getCx86(CX86_CCR3); + + /* Cyrix ARRs - everything else were excluded at the top */ + setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); + +} + +static void post_set(void) +{ + /* Flush caches and TLBs */ + wbinvd(); + + /* Cyrix ARRs - everything else was excluded at the top */ + setCx86(CX86_CCR3, ccr3); + + /* Enable caches */ + write_cr0(read_cr0() & 0xbfffffff); + + /* Restore value of CR4 */ + if ( cpu_has_pge ) + write_cr4(cr4); +} + static void cyrix_set_arr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type type) { unsigned char arr, arr_type, arr_size; - u32 cr0, ccr3; - u32 cr4 = 0; arr = CX86_ARR_BASE + (reg << 1) + reg; /* avoid multiplication by 3 */ @@ -158,24 +200,7 @@ static void cyrix_set_arr(unsigned int reg, unsigned long base, } } - /* Save value of CR4 and clear Page Global Enable (bit 7) */ - if ( cpu_has_pge ) { - cr4 = read_cr4(); - write_cr4(cr4 & (unsigned char) ~(1 << 7)); - } - - /* Disable and flush caches. Note that wbinvd flushes the TLBs as - a side-effect */ - cr0 = read_cr0() | 0x40000000; - wbinvd(); - write_cr0(cr0); - wbinvd(); - - /* Cyrix ARRs - everything else were excluded at the top */ - ccr3 = getCx86(CX86_CCR3); - - /* Cyrix ARRs - everything else were excluded at the top */ - setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); + prepare_set(); base <<= PAGE_SHIFT; setCx86(arr, ((unsigned char *) &base)[3]); @@ -183,18 +208,7 @@ static void cyrix_set_arr(unsigned int reg, unsigned long base, setCx86(arr + 2, (((unsigned char *) &base)[1]) | arr_size); setCx86(CX86_RCR_BASE + reg, arr_type); - /* Flush caches and TLBs */ - wbinvd(); - - /* Cyrix ARRs - everything else was excluded at the top */ - setCx86(CX86_CCR3, ccr3); - - /* Enable caches */ - write_cr0(read_cr0() & 0xbfffffff); - - /* Restore value of CR4 */ - if ( cpu_has_pge ) - write_cr4(cr4); + post_set(); } typedef struct { @@ -210,31 +224,11 @@ arr_state_t arr_state[8] __initdata = { unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 }; -static void __init -cyrix_arr_init_secondary(void) +static void cyrix_set_all(void) { int i; - u32 cr0, ccr3, cr4 = 0; - - /* flush cache and enable MAPEN */ - /* Save value of CR4 and clear Page Global Enable (bit 7) */ - if ( cpu_has_pge ) { - cr4 = read_cr4(); - write_cr4(cr4 & (unsigned char) ~(1 << 7)); - } - /* Disable and flush caches. Note that wbinvd flushes the TLBs as - a side-effect */ - cr0 = read_cr0() | 0x40000000; - wbinvd(); - write_cr0(cr0); - wbinvd(); - - /* Cyrix ARRs - everything else were excluded at the top */ - ccr3 = getCx86(CX86_CCR3); - - /* Cyrix ARRs - everything else were excluded at the top */ - setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); + prepare_set(); /* the CCRs are not contiguous */ for (i = 0; i < 4; i++) @@ -245,18 +239,7 @@ cyrix_arr_init_secondary(void) cyrix_set_arr(i, arr_state[i].base, arr_state[i].size, arr_state[i].type); - /* Flush caches and TLBs */ - wbinvd(); - - /* Cyrix ARRs - everything else was excluded at the top */ - setCx86(CX86_CCR3, ccr3); - - /* Enable caches */ - write_cr0(read_cr0() & 0xbfffffff); - - /* Restore value of CR4 */ - if ( cpu_has_pge ) - write_cr4(cr4); + post_set(); } /* @@ -361,7 +344,7 @@ cyrix_arr_init(void) static struct mtrr_ops cyrix_mtrr_ops = { .vendor = X86_VENDOR_CYRIX, .init = cyrix_arr_init, - .init_secondary = cyrix_arr_init_secondary, + .set_all = cyrix_set_all, .set = cyrix_set_arr, .get = cyrix_get_arr, .get_free_region = cyrix_get_free_region, diff --git a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c index e33831835119..eeefde58dcc1 100644 --- a/arch/i386/kernel/cpu/mtrr/generic.c +++ b/arch/i386/kernel/cpu/mtrr/generic.c @@ -1,3 +1,5 @@ +#include <linux/init.h> +#include <linux/slab.h> #include <linux/mm.h> #include <asm/io.h> #include <asm/mtrr.h> @@ -6,6 +8,90 @@ #include <asm/cpufeature.h> #include "mtrr.h" +struct mtrr_state { + struct mtrr_var_range *var_ranges; + mtrr_type fixed_ranges[NUM_FIXED_RANGES]; + unsigned char enabled; + mtrr_type def_type; +}; + +static unsigned long smp_changes_mask __initdata = 0; +struct mtrr_state mtrr_state = {}; + + +/* Get the MSR pair relating to a var range */ +static void __init +get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr) +{ + rdmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi); + rdmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi); +} + +static void __init +get_fixed_ranges(mtrr_type * frs) +{ + unsigned long *p = (unsigned long *) frs; + int i; + + rdmsr(MTRRfix64K_00000_MSR, p[0], p[1]); + + for (i = 0; i < 2; i++) + rdmsr(MTRRfix16K_80000_MSR + i, p[2 + i * 2], p[3 + i * 2]); + for (i = 0; i < 8; i++) + rdmsr(MTRRfix4K_C0000_MSR + i, p[6 + i * 2], p[7 + i * 2]); +} + +/* Grab all of the MTRR state for this CPU into *state */ +void get_mtrr_state(void) +{ + unsigned int i; + struct mtrr_var_range *vrs; + unsigned long lo, dummy; + + if (!mtrr_state.var_ranges) { + mtrr_state.var_ranges = kmalloc(num_var_ranges * sizeof (struct mtrr_var_range), + GFP_KERNEL); + if (!mtrr_state.var_ranges) + return; + } + vrs = mtrr_state.var_ranges; + + for (i = 0; i < num_var_ranges; i++) + get_mtrr_var_range(i, &vrs[i]); + get_fixed_ranges(mtrr_state.fixed_ranges); + + rdmsr(MTRRdefType_MSR, lo, dummy); + mtrr_state.def_type = (lo & 0xff); + mtrr_state.enabled = (lo & 0xc00) >> 10; +} + +/* Free resources associated with a struct mtrr_state */ +void __init finalize_mtrr_state(void) +{ + if (mtrr_state.var_ranges) + kfree(mtrr_state.var_ranges); + mtrr_state.var_ranges = NULL; +} + +/* Some BIOS's are fucked and don't set all MTRRs the same! */ +void __init mtrr_state_warn(void) +{ + unsigned long mask = smp_changes_mask; + + if (!mask) + return; + if (mask & MTRR_CHANGE_MASK_FIXED) + printk + ("mtrr: your CPUs had inconsistent fixed MTRR settings\n"); + if (mask & MTRR_CHANGE_MASK_VARIABLE) + printk + ("mtrr: your CPUs had inconsistent variable MTRR settings\n"); + if (mask & MTRR_CHANGE_MASK_DEFTYPE) + printk + ("mtrr: your CPUs had inconsistent MTRRdefType settings\n"); + printk("mtrr: probably your BIOS does not setup all CPUs\n"); +} + int generic_get_free_region(unsigned long base, unsigned long size) /* [SUMMARY] Get a free MTRR. @@ -55,23 +141,104 @@ void generic_get_mtrr(unsigned int reg, unsigned long *base, *type = base_lo & 0xff; } -void generic_set_mtrr(unsigned int reg, unsigned long base, - unsigned long size, mtrr_type type) -/* [SUMMARY] Set variable MTRR register on the local CPU. - <reg> The register to set. - <base> The base address of the region. - <size> The size of the region. If this is 0 the region is disabled. - <type> The type of the region. - <do_safe> If TRUE, do the change safely. If FALSE, safety measures should - be done externally. - [RETURNS] Nothing. +static int __init set_fixed_ranges(mtrr_type * frs) +{ + unsigned long *p = (unsigned long *) frs; + int changed = FALSE; + int i; + unsigned long lo, hi; + + rdmsr(MTRRfix64K_00000_MSR, lo, hi); + if (p[0] != lo || p[1] != hi) { + wrmsr(MTRRfix64K_00000_MSR, p[0], p[1]); + changed = TRUE; + } + + for (i = 0; i < 2; i++) { + rdmsr(MTRRfix16K_80000_MSR + i, lo, hi); + if (p[2 + i * 2] != lo || p[3 + i * 2] != hi) { + wrmsr(MTRRfix16K_80000_MSR + i, p[2 + i * 2], + p[3 + i * 2]); + changed = TRUE; + } + } + + for (i = 0; i < 8; i++) { + rdmsr(MTRRfix4K_C0000_MSR + i, lo, hi); + if (p[6 + i * 2] != lo || p[7 + i * 2] != hi) { + wrmsr(MTRRfix4K_C0000_MSR + i, p[6 + i * 2], + p[7 + i * 2]); + changed = TRUE; + } + } + return changed; +} + +/* Set the MSR pair relating to a var range. Returns TRUE if + changes are made */ +static int __init set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr) +{ + unsigned int lo, hi; + int changed = FALSE; + + rdmsr(MTRRphysBase_MSR(index), lo, hi); + if ((vr->base_lo & 0xfffff0ffUL) != (lo & 0xfffff0ffUL) + || (vr->base_hi & 0xfUL) != (hi & 0xfUL)) { + wrmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi); + changed = TRUE; + } + + rdmsr(MTRRphysMask_MSR(index), lo, hi); + + if ((vr->mask_lo & 0xfffff800UL) != (lo & 0xfffff800UL) + || (vr->mask_hi & 0xfUL) != (hi & 0xfUL)) { + wrmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi); + changed = TRUE; + } + return changed; +} + +static unsigned long set_mtrr_state(u32 deftype_lo, u32 deftype_hi) +/* [SUMMARY] Set the MTRR state for this CPU. + <state> The MTRR state information to read. + <ctxt> Some relevant CPU context. + [NOTE] The CPU must already be in a safe state for MTRR changes. + [RETURNS] 0 if no changes made, else a mask indication what was changed. */ { - u32 cr0, cr4 = 0; - u32 deftype_lo, deftype_hi; - static spinlock_t set_atomicity_lock = SPIN_LOCK_UNLOCKED; + unsigned int i; + unsigned long change_mask = 0; + + for (i = 0; i < num_var_ranges; i++) + if (set_mtrr_var_ranges(i, &mtrr_state.var_ranges[i])) + change_mask |= MTRR_CHANGE_MASK_VARIABLE; + + if (set_fixed_ranges(mtrr_state.fixed_ranges)) + change_mask |= MTRR_CHANGE_MASK_FIXED; + + /* Set_mtrr_restore restores the old value of MTRRdefType, + so to set it we fiddle with the saved value */ + if ((deftype_lo & 0xff) != mtrr_state.def_type + || ((deftype_lo & 0xc00) >> 10) != mtrr_state.enabled) { + deftype_lo |= (mtrr_state.def_type | mtrr_state.enabled << 10); + change_mask |= MTRR_CHANGE_MASK_DEFTYPE; + } + + return change_mask; +} + + +static u32 cr4 = 0; +static u32 deftype_lo, deftype_hi; + +static void prepare_set(void) +{ + u32 cr0; + + /* Note that this is not ideal, since the cache is only flushed/disabled + for this CPU while the MTRRs are changed, but changing this requires + more invasive changes to the way the kernel boots */ - spin_lock(&set_atomicity_lock); /* Save value of CR4 and clear Page Global Enable (bit 7) */ if ( cpu_has_pge ) { cr4 = read_cr4(); @@ -90,18 +257,10 @@ void generic_set_mtrr(unsigned int reg, unsigned long base, /* Disable MTRRs, and set the default type to uncached */ wrmsr(MTRRdefType_MSR, deftype_lo & 0xf300UL, deftype_hi); +} - if (size == 0) { - /* The invalid bit is kept in the mask, so we simply clear the - relevant mask register to disable a range. */ - wrmsr(MTRRphysMask_MSR(reg), 0, 0); - } else { - wrmsr(MTRRphysBase_MSR(reg), base << PAGE_SHIFT | type, - (base & size_and_mask) >> (32 - PAGE_SHIFT)); - wrmsr(MTRRphysMask_MSR(reg), -size << PAGE_SHIFT | 0x800, - (-size & size_and_mask) >> (32 - PAGE_SHIFT)); - } - +static void post_set(void) +{ /* Flush caches and TLBs */ wbinvd(); @@ -114,7 +273,57 @@ void generic_set_mtrr(unsigned int reg, unsigned long base, /* Restore value of CR4 */ if ( cpu_has_pge ) write_cr4(cr4); - spin_unlock(&set_atomicity_lock); + +} + +static void generic_set_all(void) +{ + unsigned long mask, count; + + prepare_set(); + + /* Actually set the state */ + mask = set_mtrr_state(deftype_lo,deftype_hi); + + post_set(); + + /* Use the atomic bitops to update the global mask */ + for (count = 0; count < sizeof mask * 8; ++count) { + if (mask & 0x01) + set_bit(count, &smp_changes_mask); + mask >>= 1; + } + +} + +static void generic_set_mtrr(unsigned int reg, unsigned long base, + unsigned long size, mtrr_type type) +/* [SUMMARY] Set variable MTRR register on the local CPU. + <reg> The register to set. + <base> The base address of the region. + <size> The size of the region. If this is 0 the region is disabled. + <type> The type of the region. + <do_safe> If TRUE, do the change safely. If FALSE, safety measures should + be done externally. + [RETURNS] Nothing. +*/ +{ + prepare_set(); + + printk("MTRR: setting reg %x\n",reg); + + if (size == 0) { + /* The invalid bit is kept in the mask, so we simply clear the + relevant mask register to disable a range. */ + wrmsr(MTRRphysMask_MSR(reg), 0, 0); + } else { + wrmsr(MTRRphysBase_MSR(reg), base << PAGE_SHIFT | type, + (base & size_and_mask) >> (32 - PAGE_SHIFT)); + wrmsr(MTRRphysMask_MSR(reg), -size << PAGE_SHIFT | 0x800, + (-size & size_and_mask) >> (32 - PAGE_SHIFT)); + } + + post_set(); } int generic_validate_add_page(unsigned long base, unsigned long size, unsigned int type) @@ -178,7 +387,7 @@ int positive_have_wrcomb(void) */ struct mtrr_ops generic_mtrr_ops = { .use_intel_if = 1, - .init_secondary = generic_init_secondary, + .set_all = generic_set_all, .get = generic_get_mtrr, .get_free_region = generic_get_free_region, .set = generic_set_mtrr, diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c index 8f0d8a3c8bd7..aa091d2c5db7 100644 --- a/arch/i386/kernel/cpu/mtrr/main.c +++ b/arch/i386/kernel/cpu/mtrr/main.c @@ -163,8 +163,11 @@ static void ipi_handler(void *info) } /* The master has cleared me to execute */ - mtrr_if->set(data->smp_reg, data->smp_base, - data->smp_size, data->smp_type); + if (data->smp_reg != ~0UL) + mtrr_if->set(data->smp_reg, data->smp_base, + data->smp_size, data->smp_type); + else + mtrr_if->set_all(); atomic_dec(&data->count); while(atomic_read(&data->gate)) { @@ -243,7 +246,15 @@ static void set_mtrr(unsigned int reg, unsigned long base, atomic_set(&data.gate,1); /* do our MTRR business */ - mtrr_if->set(reg,base,size,type); + + /* HACK! + * We use this same function to initialize the mtrrs on boot. + * The state of the boot cpu's mtrrs has been saved, and we want + * to replicate across all the APs. + * If we're doing that @reg is set to something special... + */ + if (reg != ~0UL) + mtrr_if->set(reg,base,size,type); /* wait for the others */ while(atomic_read(&data.count)) { @@ -530,6 +541,20 @@ static void __init init_ifs(void) centaur_init_mtrr(); } +static void init_other_cpus(void) +{ + if (use_intel()) + get_mtrr_state(); + + /* bring up the other processors */ + set_mtrr(~0UL,0,0,0); + + if (use_intel()) { + finalize_mtrr_state(); + mtrr_state_warn(); + } +} + /** * mtrr_init - initialie mtrrs on the boot CPU * @@ -537,7 +562,7 @@ static void __init init_ifs(void) * initialized (i.e. before smp_init()). * */ -int __init mtrr_init(void) +static int __init mtrr_init(void) { init_ifs(); @@ -608,21 +633,15 @@ int __init mtrr_init(void) break; } } + printk("mtrr: v%s\n",MTRR_VERSION); + if (mtrr_if) { set_num_var_ranges(); - if (use_intel()) { - /* Only for Intel MTRRs */ - get_mtrr_state(); - } init_table(); + init_other_cpus(); } -#if 0 - printk("mtrr: v%s Richard Gooch (rgooch@atnf.csiro.au)\n" - "mtrr: detected mtrr type: %s\n", - MTRR_VERSION, mtrr_if_name[mtrr_if]); -#endif return mtrr_if ? -ENXIO : 0; } -//subsys_initcall(mtrr_init); +core_initcall(mtrr_init); diff --git a/arch/i386/kernel/cpu/mtrr/mtrr.h b/arch/i386/kernel/cpu/mtrr/mtrr.h index 5c1aa8ab552e..363a5b14acdc 100644 --- a/arch/i386/kernel/cpu/mtrr/mtrr.h +++ b/arch/i386/kernel/cpu/mtrr/mtrr.h @@ -38,9 +38,10 @@ struct mtrr_ops { u32 vendor; u32 use_intel_if; void (*init)(void); - void (*init_secondary)(void); void (*set)(unsigned int reg, unsigned long base, unsigned long size, mtrr_type type); + void (*set_all)(void); + void (*get)(unsigned int reg, unsigned long *base, unsigned long *size, mtrr_type * type); int (*get_free_region) (unsigned long base, unsigned long size); diff --git a/arch/i386/kernel/cpu/mtrr/state.c b/arch/i386/kernel/cpu/mtrr/state.c index a2eef500f7bc..3d32fbf35284 100644 --- a/arch/i386/kernel/cpu/mtrr/state.c +++ b/arch/i386/kernel/cpu/mtrr/state.c @@ -1,180 +1,10 @@ #include <linux/mm.h> -#include <linux/slab.h> #include <linux/init.h> #include <asm/io.h> #include <asm/mtrr.h> #include <asm/msr.h> #include "mtrr.h" -struct mtrr_state { - struct mtrr_var_range *var_ranges; - mtrr_type fixed_ranges[NUM_FIXED_RANGES]; - unsigned char enabled; - mtrr_type def_type; -}; - -static unsigned long smp_changes_mask __initdata = 0; -struct mtrr_state mtrr_state = {}; - -static int __init set_fixed_ranges(mtrr_type * frs) -{ - unsigned long *p = (unsigned long *) frs; - int changed = FALSE; - int i; - unsigned long lo, hi; - - rdmsr(MTRRfix64K_00000_MSR, lo, hi); - if (p[0] != lo || p[1] != hi) { - wrmsr(MTRRfix64K_00000_MSR, p[0], p[1]); - changed = TRUE; - } - - for (i = 0; i < 2; i++) { - rdmsr(MTRRfix16K_80000_MSR + i, lo, hi); - if (p[2 + i * 2] != lo || p[3 + i * 2] != hi) { - wrmsr(MTRRfix16K_80000_MSR + i, p[2 + i * 2], - p[3 + i * 2]); - changed = TRUE; - } - } - - for (i = 0; i < 8; i++) { - rdmsr(MTRRfix4K_C0000_MSR + i, lo, hi); - if (p[6 + i * 2] != lo || p[7 + i * 2] != hi) { - wrmsr(MTRRfix4K_C0000_MSR + i, p[6 + i * 2], - p[7 + i * 2]); - changed = TRUE; - } - } - return changed; -} - -/* Set the MSR pair relating to a var range. Returns TRUE if - changes are made */ -static int __init set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr) -{ - unsigned int lo, hi; - int changed = FALSE; - - rdmsr(MTRRphysBase_MSR(index), lo, hi); - if ((vr->base_lo & 0xfffff0ffUL) != (lo & 0xfffff0ffUL) - || (vr->base_hi & 0xfUL) != (hi & 0xfUL)) { - wrmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi); - changed = TRUE; - } - - rdmsr(MTRRphysMask_MSR(index), lo, hi); - - if ((vr->mask_lo & 0xfffff800UL) != (lo & 0xfffff800UL) - || (vr->mask_hi & 0xfUL) != (hi & 0xfUL)) { - wrmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi); - changed = TRUE; - } - return changed; -} - -static unsigned long set_mtrr_state(u32 deftype_lo, u32 deftype_hi) -/* [SUMMARY] Set the MTRR state for this CPU. - <state> The MTRR state information to read. - <ctxt> Some relevant CPU context. - [NOTE] The CPU must already be in a safe state for MTRR changes. - [RETURNS] 0 if no changes made, else a mask indication what was changed. -*/ -{ - unsigned int i; - unsigned long change_mask = 0; - - for (i = 0; i < num_var_ranges; i++) - if (set_mtrr_var_ranges(i, &mtrr_state.var_ranges[i])) - change_mask |= MTRR_CHANGE_MASK_VARIABLE; - - if (set_fixed_ranges(mtrr_state.fixed_ranges)) - change_mask |= MTRR_CHANGE_MASK_FIXED; - - /* Set_mtrr_restore restores the old value of MTRRdefType, - so to set it we fiddle with the saved value */ - if ((deftype_lo & 0xff) != mtrr_state.def_type - || ((deftype_lo & 0xc00) >> 10) != mtrr_state.enabled) { - deftype_lo |= (mtrr_state.def_type | mtrr_state.enabled << 10); - change_mask |= MTRR_CHANGE_MASK_DEFTYPE; - } - - return change_mask; -} - - -/* Some BIOS's are fucked and don't set all MTRRs the same! */ -static void __init mtrr_state_warn(void) -{ - unsigned long mask = smp_changes_mask; - if (!mask) - return; - if (mask & MTRR_CHANGE_MASK_FIXED) - printk - ("mtrr: your CPUs had inconsistent fixed MTRR settings\n"); - if (mask & MTRR_CHANGE_MASK_VARIABLE) - printk - ("mtrr: your CPUs had inconsistent variable MTRR settings\n"); - if (mask & MTRR_CHANGE_MASK_DEFTYPE) - printk - ("mtrr: your CPUs had inconsistent MTRRdefType settings\n"); - printk("mtrr: probably your BIOS does not setup all CPUs\n"); -} - -/* Free resources associated with a struct mtrr_state */ -static void __init finalize_mtrr_state(void) -{ - if (mtrr_state.var_ranges) - kfree(mtrr_state.var_ranges); - mtrr_state.var_ranges = NULL; -} - -/* Get the MSR pair relating to a var range */ -static void __init -get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr) -{ - rdmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi); - rdmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi); -} - -static void __init -get_fixed_ranges(mtrr_type * frs) -{ - unsigned long *p = (unsigned long *) frs; - int i; - - rdmsr(MTRRfix64K_00000_MSR, p[0], p[1]); - - for (i = 0; i < 2; i++) - rdmsr(MTRRfix16K_80000_MSR + i, p[2 + i * 2], p[3 + i * 2]); - for (i = 0; i < 8; i++) - rdmsr(MTRRfix4K_C0000_MSR + i, p[6 + i * 2], p[7 + i * 2]); -} - -/* Grab all of the MTRR state for this CPU into *state */ -void get_mtrr_state(void) -{ - unsigned int i; - struct mtrr_var_range *vrs; - unsigned long lo, dummy; - - if (!mtrr_state.var_ranges) { - mtrr_state.var_ranges = kmalloc(num_var_ranges * sizeof (struct mtrr_var_range), - GFP_KERNEL); - if (!mtrr_state.var_ranges) - return; - } - vrs = mtrr_state.var_ranges; - - for (i = 0; i < num_var_ranges; i++) - get_mtrr_var_range(i, &vrs[i]); - get_fixed_ranges(mtrr_state.fixed_ranges); - - rdmsr(MTRRdefType_MSR, lo, dummy); - mtrr_state.def_type = (lo & 0xff); - mtrr_state.enabled = (lo & 0xc00) >> 10; -} - /* Put the processor into a state where MTRRs can be safely set */ void set_mtrr_prepare_save(struct set_mtrr_context *ctxt) @@ -246,93 +76,3 @@ void set_mtrr_done(struct set_mtrr_context *ctxt) local_irq_restore(ctxt->flags); } -void __init generic_init_secondary(void) -{ - u32 cr0, cr4 = 0; - u32 deftype_lo, deftype_hi; - unsigned long mask, count; - - /* Note that this is not ideal, since the cache is only flushed/disabled - for this CPU while the MTRRs are changed, but changing this requires - more invasive changes to the way the kernel boots */ - - /* Save value of CR4 and clear Page Global Enable (bit 7) */ - if ( cpu_has_pge ) { - cr4 = read_cr4(); - write_cr4(cr4 & (unsigned char) ~(1 << 7)); - } - - /* Disable and flush caches. Note that wbinvd flushes the TLBs as - a side-effect */ - cr0 = read_cr0() | 0x40000000; - wbinvd(); - write_cr0(cr0); - wbinvd(); - - /* Save MTRR state */ - rdmsr(MTRRdefType_MSR, deftype_lo, deftype_hi); - - /* Disable MTRRs, and set the default type to uncached */ - wrmsr(MTRRdefType_MSR, deftype_lo & 0xf300UL, deftype_hi); - - /* Actually set the state */ - mask = set_mtrr_state(deftype_lo,deftype_hi); - - /* Flush caches and TLBs */ - wbinvd(); - - /* Intel (P6) standard MTRRs */ - wrmsr(MTRRdefType_MSR, deftype_lo, deftype_hi); - - /* Enable caches */ - write_cr0(read_cr0() & 0xbfffffff); - - /* Restore value of CR4 */ - if ( cpu_has_pge ) - write_cr4(cr4); - - /* Use the atomic bitops to update the global mask */ - for (count = 0; count < sizeof mask * 8; ++count) { - if (mask & 0x01) - set_bit(count, &smp_changes_mask); - mask >>= 1; - } -} - -/** - * mtrr_init_secondary - setup AP MTRR state - * - * Yes, this code is exactly the same as the set_mtrr code, except for the - * piece in the middle - you set all the ranges at once, instead of one - * register at a time. - * Shoot me. - */ -void __init mtrr_init_secondary_cpu(void) -{ - unsigned long flags; - - if (!mtrr_if || !mtrr_if->init_secondary) { - /* I see no MTRRs I can support in SMP mode... */ - printk("mtrr: SMP support incomplete for this vendor\n"); - return; - } - - local_irq_save(flags); - mtrr_if->init_secondary(); - local_irq_restore(flags); -} - -/** - * mtrr_final_init - finalize initialization sequence. - */ -static int __init mtrr_finalize_state(void) -{ - if (use_intel()) { - finalize_mtrr_state(); - mtrr_state_warn(); - } - return 0; -} - -arch_initcall(mtrr_finalize_state); - diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 936ee9e5fbb2..dc115fbe7492 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -45,7 +45,6 @@ #include <linux/delay.h> #include <linux/mc146818rtc.h> -#include <asm/mtrr.h> #include <asm/pgalloc.h> #include <asm/tlbflush.h> #include <asm/smpboot.h> @@ -403,12 +402,6 @@ void __init smp_callin(void) local_irq_enable(); -#ifdef CONFIG_MTRR - /* - * Must be done before calibration delay is computed - */ - mtrr_init_secondary_cpu (); -#endif /* * Get our bogomips. */ diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index a32314075d1d..ae3e803a5368 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -115,7 +115,7 @@ static inline unsigned long do_fast_gettimeoffset(void) return delay_at_last_interrupt + edx; } -#define TICK_SIZE tick +#define TICK_SIZE (tick_nsec / 1000) spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED; EXPORT_SYMBOL(i8253_lock); @@ -280,7 +280,7 @@ void do_gettimeofday(struct timeval *tv) usec += lost * (1000000 / HZ); } sec = xtime.tv_sec; - usec += xtime.tv_usec; + usec += (xtime.tv_nsec / 1000); read_unlock_irqrestore(&xtime_lock, flags); while (usec >= 1000000) { @@ -309,7 +309,8 @@ void do_settimeofday(struct timeval *tv) tv->tv_sec--; } - xtime = *tv; + xtime.tv_sec = tv->tv_sec; + xtime.tv_nsec = (tv->tv_usec * 1000); time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; @@ -437,8 +438,8 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg */ if ((time_status & STA_UNSYNC) == 0 && xtime.tv_sec > last_rtc_update + 660 && - xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 && - xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) { + (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && + (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { if (set_rtc_mmss(xtime.tv_sec) == 0) last_rtc_update = xtime.tv_sec; else @@ -655,7 +656,7 @@ void __init time_init(void) extern int x86_udelay_tsc; xtime.tv_sec = get_cmos_time(); - xtime.tv_usec = 0; + xtime.tv_nsec = 0; /* * If we have APM enabled or the CPU clock speed is variable diff --git a/drivers/acpi/Config.in b/drivers/acpi/Config.in index 4017cca560b4..bc38750060c4 100644 --- a/drivers/acpi/Config.in +++ b/drivers/acpi/Config.in @@ -2,91 +2,78 @@ # ACPI Configuration # -if [ "$CONFIG_X86" = "y" ]; then - - mainmenu_option next_comment - comment 'ACPI Support' - bool 'ACPI Support' CONFIG_ACPI - if [ "$CONFIG_ACPI" = "y" ]; then - if [ "$CONFIG_X86_LOCAL_APIC" = "y" ]; then - bool 'CPU Enumeration Only' CONFIG_ACPI_HT_ONLY - fi +mainmenu_option next_comment +comment 'ACPI Support' - if [ "$CONFIG_ACPI_HT_ONLY" = "y" ]; then - define_bool CONFIG_ACPI_BOOT y - else - define_bool CONFIG_ACPI_BOOT y - define_bool CONFIG_ACPI_BUS y - define_bool CONFIG_ACPI_INTERPRETER y - define_bool CONFIG_ACPI_EC y - define_bool CONFIG_ACPI_POWER y - if [ "$CONFIG_PCI" = "y" ]; then - define_bool CONFIG_ACPI_PCI y - fi - define_bool CONFIG_ACPI_SLEEP $CONFIG_SOFTWARE_SUSPEND - define_bool CONFIG_ACPI_SYSTEM y - tristate ' AC Adapter' CONFIG_ACPI_AC - tristate ' Battery' CONFIG_ACPI_BATTERY - tristate ' Button' CONFIG_ACPI_BUTTON - tristate ' Fan' CONFIG_ACPI_FAN - tristate ' Processor' CONFIG_ACPI_PROCESSOR - dep_tristate ' Thermal Zone' CONFIG_ACPI_THERMAL $CONFIG_ACPI_PROCESSOR - if [ "$CONFIG_NUMA" = "y" ]; then - dep_bool ' NUMA support' CONFIG_ACPI_NUMA $CONFIG_NUMA +if [ "$CONFIG_X86" = "y" ]; then + bool 'ACPI Support' CONFIG_ACPI + if [ "$CONFIG_ACPI" = "y" ]; then + if [ "$CONFIG_X86_LOCAL_APIC" = "y" ]; then + bool 'CPU Enumeration Only' CONFIG_ACPI_HT_ONLY fi - tristate ' Toshiba Laptop Extras' CONFIG_ACPI_TOSHIBA - bool ' Debug Statements' CONFIG_ACPI_DEBUG - fi - fi - endmenu + define_bool CONFIG_ACPI_BOOT y -fi + if [ "$CONFIG_ACPI_HT_ONLY" != "y" ]; then + tristate ' AC Adapter' CONFIG_ACPI_AC + tristate ' Battery' CONFIG_ACPI_BATTERY + tristate ' Button' CONFIG_ACPI_BUTTON + tristate ' Fan' CONFIG_ACPI_FAN + tristate ' Processor' CONFIG_ACPI_PROCESSOR + dep_tristate ' Thermal Zone' CONFIG_ACPI_THERMAL $CONFIG_ACPI_PROCESSOR + if [ "$CONFIG_NUMA" = "y" ]; then + dep_bool ' NUMA support' CONFIG_ACPI_NUMA $CONFIG_NUMA + fi + tristate ' Toshiba Laptop Extras' CONFIG_ACPI_TOSHIBA + bool ' Debug Statements' CONFIG_ACPI_DEBUG + define_bool CONFIG_ACPI_BOOT y + define_bool CONFIG_ACPI_BUS y + define_bool CONFIG_ACPI_INTERPRETER y + define_bool CONFIG_ACPI_EC y + define_bool CONFIG_ACPI_POWER y + define_bool CONFIG_ACPI_PCI $CONFIG_PCI + define_bool CONFIG_ACPI_SLEEP $CONFIG_SOFTWARE_SUSPEND + define_bool CONFIG_ACPI_SYSTEM y + fi + fi +fi if [ "$CONFIG_IA64" = "y" ]; then + if [ "$CONFIG_IA64_SGI_SN" = "y" ]; then + define_bool CONFIG_ACPI y + define_bool CONFIG_ACPI_EFI y + define_bool CONFIG_ACPI_BOOT y + define_bool CONFIG_ACPI_BUS n + define_bool CONFIG_ACPI_INTERPRETER n + define_bool CONFIG_ACPI_PCI n + define_bool CONFIG_ACPI_POWER n + define_bool CONFIG_ACPI_SYSTEM n + define_bool CONFIG_ACPI_BUTTON n + define_bool CONFIG_ACPI_FAN n + define_bool CONFIG_ACPI_PROCESSOR n + define_bool CONFIG_ACPI_THERMAL n + define_bool CONFIG_ACPI_NUMA y + fi - if [ "$CONFIG_IA64_SGI_SN" = "y" ]; then - mainmenu_option next_comment - comment 'ACPI Support' - define_bool CONFIG_ACPI y - define_bool CONFIG_ACPI_EFI y - define_bool CONFIG_ACPI_BOOT y - define_bool CONFIG_ACPI_BUS n - define_bool CONFIG_ACPI_INTERPRETER n - define_bool CONFIG_ACPI_PCI n - define_bool CONFIG_ACPI_POWER n - define_bool CONFIG_ACPI_SYSTEM n - define_bool CONFIG_ACPI_BUTTON n - define_bool CONFIG_ACPI_FAN n - define_bool CONFIG_ACPI_PROCESSOR n - define_bool CONFIG_ACPI_THERMAL n - define_bool CONFIG_ACPI_NUMA y - endmenu - fi - - if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then - mainmenu_option next_comment - comment 'ACPI Support' - if [ "$CONFIG_PCI" = "y" ]; then - define_bool CONFIG_ACPI_PCI y - fi - define_bool CONFIG_ACPI y - define_bool CONFIG_ACPI_EFI y - define_bool CONFIG_ACPI_BOOT y - define_bool CONFIG_ACPI_BUS y - define_bool CONFIG_ACPI_INTERPRETER y - define_bool CONFIG_ACPI_POWER y - define_bool CONFIG_ACPI_SYSTEM y - tristate ' Button' CONFIG_ACPI_BUTTON - tristate ' Fan' CONFIG_ACPI_FAN - tristate ' Processor' CONFIG_ACPI_PROCESSOR - dep_tristate ' Thermal Zone' CONFIG_ACPI_THERMAL $CONFIG_ACPI_PROCESSOR - if [ "$CONFIG_NUMA" = "y" ]; then - dep_bool ' NUMA support' CONFIG_ACPI_NUMA $CONFIG_NUMA - fi - bool ' Debug Statements' CONFIG_ACPI_DEBUG - endmenu - fi - + if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then + tristate ' Button' CONFIG_ACPI_BUTTON + tristate ' Fan' CONFIG_ACPI_FAN + tristate ' Processor' CONFIG_ACPI_PROCESSOR + dep_tristate ' Thermal Zone' CONFIG_ACPI_THERMAL $CONFIG_ACPI_PROCESSOR + if [ "$CONFIG_NUMA" = "y" ]; then + dep_bool ' NUMA support' CONFIG_ACPI_NUMA $CONFIG_NUMA + fi + bool ' Debug Statements' CONFIG_ACPI_DEBUG + define_bool CONFIG_ACPI_PCI $CONFIG_PCI + define_bool CONFIG_ACPI y + define_bool CONFIG_ACPI_EFI y + define_bool CONFIG_ACPI_BOOT y + define_bool CONFIG_ACPI_BUS y + define_bool CONFIG_ACPI_INTERPRETER y + define_bool CONFIG_ACPI_POWER y + define_bool CONFIG_ACPI_SYSTEM y + fi fi + +endmenu diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index c9faecf0e450..e4acfd8b1b35 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -51,7 +51,7 @@ static struct acpi_driver acpi_ac_driver = { .class = ACPI_AC_CLASS, .ids = ACPI_AC_HID, .ops = { - .add = acpi_ac_add, + .add = acpi_ac_add, .remove = acpi_ac_remove, }, }; diff --git a/drivers/acpi/acpi_ksyms.c b/drivers/acpi/acpi_ksyms.c index 91e2ac7835cc..ea2a02fc5794 100644 --- a/drivers/acpi/acpi_ksyms.c +++ b/drivers/acpi/acpi_ksyms.c @@ -114,6 +114,7 @@ EXPORT_SYMBOL(acpi_evaluate_reference); #ifdef CONFIG_ACPI_BUS EXPORT_SYMBOL(acpi_fadt); +EXPORT_SYMBOL(acpi_walk_namespace); EXPORT_SYMBOL(acpi_root_dir); EXPORT_SYMBOL(acpi_bus_get_device); EXPORT_SYMBOL(acpi_bus_get_status); @@ -127,4 +128,3 @@ EXPORT_SYMBOL(acpi_bus_scan); EXPORT_SYMBOL(acpi_init); #endif /*CONFIG_ACPI_BUS*/ - diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 6a096d8c1463..53aeed0c0dc5 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -162,7 +162,7 @@ acpi_battery_get_info ( } end: - kfree(buffer.pointer); + acpi_os_free(buffer.pointer); if (!result) (*bif) = (struct acpi_battery_info *) data.pointer; @@ -223,7 +223,7 @@ acpi_battery_get_status ( } end: - kfree(buffer.pointer); + acpi_os_free(buffer.pointer); if (!result) (*bst) = (struct acpi_battery_status *) data.pointer; diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 7e37a2500026..e5f08346cd84 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -32,7 +32,9 @@ #include <linux/sched.h> #include <linux/pm.h> #include <linux/proc_fs.h> +#ifdef CONFIG_X86 #include <asm/mpspec.h> +#endif #include "acpi_bus.h" #include "acpi_drivers.h" #include "include/acinterp.h" /* for acpi_ex_eisa_id_to_string() */ @@ -665,7 +667,7 @@ acpi_bus_generate_event ( if (!event_is_open) return_VALUE(0); - event = kmalloc(sizeof(struct acpi_bus_event), GFP_KERNEL); + event = kmalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC); if (!event) return_VALUE(-ENOMEM); @@ -1967,11 +1969,13 @@ acpi_bus_init (void) goto error1; } +#ifdef CONFIG_X86 /* Ensure the SCI is set to level-triggered, active-low */ if (acpi_ioapic) mp_override_legacy_irq(acpi_fadt.sci_int, 3, 3, acpi_fadt.sci_int); else eisa_set_level_irq(acpi_fadt.sci_int); +#endif status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index cdd6c926ea5c..594149498463 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -70,7 +70,6 @@ struct acpi_button { static struct proc_dir_entry *acpi_button_dir = NULL; - static int acpi_button_read_info ( char *page, diff --git a/drivers/acpi/debugger/Makefile b/drivers/acpi/debugger/Makefile deleted file mode 100644 index ec9debb42a26..000000000000 --- a/drivers/acpi/debugger/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for all Linux ACPI interpreter subdirectories -# - -obj-$(CONFIG_ACPI_INTERPRETER) := $(patsubst %.c,%.o,$(wildcard *.c)) - -EXTRA_CFLAGS += $(ACPI_CFLAGS) - -include $(TOPDIR)/Rules.make diff --git a/drivers/acpi/debugger/dbcmds.c b/drivers/acpi/debugger/dbcmds.c deleted file mode 100644 index 274a18d86787..000000000000 --- a/drivers/acpi/debugger/dbcmds.c +++ /dev/null @@ -1,1114 +0,0 @@ -/******************************************************************************* - * - * Module Name: dbcmds - debug commands and output routines - * $Revision: 87 $ - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2002, R. Byron Moore - * - * 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 "acpi.h" -#include "acdispat.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "acevents.h" -#include "acdebug.h" -#include "acresrc.h" -#include "acdisasm.h" - -#ifdef ACPI_DEBUGGER - -#define _COMPONENT ACPI_CA_DEBUGGER - ACPI_MODULE_NAME ("dbcmds") - - -/* - * Arguments for the Objects command - * These object types map directly to the ACPI_TYPES - */ - -static ARGUMENT_INFO acpi_db_object_types [] = -{ {"ANY"}, - {"NUMBERS"}, - {"STRINGS"}, - {"BUFFERS"}, - {"PACKAGES"}, - {"FIELDS"}, - {"DEVICES"}, - {"EVENTS"}, - {"METHODS"}, - {"MUTEXES"}, - {"REGIONS"}, - {"POWERRESOURCES"}, - {"PROCESSORS"}, - {"THERMALZONES"}, - {"BUFFERFIELDS"}, - {"DDBHANDLES"}, - {NULL} /* Must be null terminated */ -}; - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_walk_for_references - * - * PARAMETERS: Callback from Walk_namespace - * - * RETURN: Status - * - * DESCRIPTION: Check if this namespace object refers to the target object - * that is passed in as the context value. - * - * Note: Currently doesn't check subobjects within the Node's object - * - ******************************************************************************/ - -acpi_status -acpi_db_walk_for_references ( - acpi_handle obj_handle, - u32 nesting_level, - void *context, - void **return_value) -{ - acpi_operand_object *obj_desc = (acpi_operand_object *) context; - acpi_namespace_node *node = (acpi_namespace_node *) obj_handle; - - - /* Check for match against the namespace node itself */ - - if (node == (void *) obj_desc) { - acpi_os_printf ("Object is a Node [%4.4s]\n", node->name.ascii); - } - - /* Check for match against the object attached to the node */ - - if (acpi_ns_get_attached_object (node) == obj_desc) { - acpi_os_printf ("Reference at Node->Object %p [%4.4s]\n", node, node->name.ascii); - } - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_find_references - * - * PARAMETERS: Object_arg - String with hex value of the object - * - * RETURN: None - * - * DESCRIPTION: Search namespace for all references to the input object - * - ******************************************************************************/ - -void -acpi_db_find_references ( - NATIVE_CHAR *object_arg) -{ - acpi_operand_object *obj_desc; - - - /* Convert string to object pointer */ - - obj_desc = ACPI_TO_POINTER (ACPI_STRTOUL (object_arg, NULL, 16)); - - /* Search all nodes in namespace */ - - (void) acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - acpi_db_walk_for_references, (void *) obj_desc, NULL); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_display_locks - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Display information about internal mutexes. - * - ******************************************************************************/ - -void -acpi_db_display_locks (void) -{ - u32 i; - - - for (i = 0; i < MAX_MTX; i++) { - acpi_os_printf ("%26s : %s\n", acpi_ut_get_mutex_name (i), - acpi_gbl_acpi_mutex_info[i].owner_id == ACPI_MUTEX_NOT_ACQUIRED - ? "Locked" : "Unlocked"); - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_display_table_info - * - * PARAMETERS: Table_arg - String with name of table to be displayed - * - * RETURN: None - * - * DESCRIPTION: Display information about loaded tables. Current - * implementation displays all loaded tables. - * - ******************************************************************************/ - -void -acpi_db_display_table_info ( - NATIVE_CHAR *table_arg) -{ - u32 i; - - - for (i = 0; i < NUM_ACPI_TABLES; i++) { - if (acpi_gbl_acpi_tables[i].pointer) { - acpi_os_printf ("%s at %p length %X\n", acpi_gbl_acpi_table_data[i].name, - acpi_gbl_acpi_tables[i].pointer, acpi_gbl_acpi_tables[i].length); - } - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_unload_acpi_table - * - * PARAMETERS: Table_arg - Name of the table to be unloaded - * Instance_arg - Which instance of the table to unload (if - * there are multiple tables of the same type) - * - * RETURN: Nonde - * - * DESCRIPTION: Unload an ACPI table. - * Instance is not implemented - * - ******************************************************************************/ - -void -acpi_db_unload_acpi_table ( - NATIVE_CHAR *table_arg, - NATIVE_CHAR *instance_arg) -{ - u32 i; - acpi_status status; - - - /* Search all tables for the target type */ - - for (i = 0; i < NUM_ACPI_TABLES; i++) { - if (!ACPI_STRNCMP (table_arg, acpi_gbl_acpi_table_data[i].signature, - acpi_gbl_acpi_table_data[i].sig_length)) { - /* Found the table, unload it */ - - status = acpi_unload_table (i); - if (ACPI_SUCCESS (status)) { - acpi_os_printf ("[%s] unloaded and uninstalled\n", table_arg); - } - else { - acpi_os_printf ("%s, while unloading [%s]\n", - acpi_format_exception (status), table_arg); - } - - return; - } - } - - acpi_os_printf ("Unknown table type [%s]\n", table_arg); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_set_method_breakpoint - * - * PARAMETERS: Location - AML offset of breakpoint - * Walk_state - Current walk info - * Op - Current Op (from parse walk) - * - * RETURN: None - * - * DESCRIPTION: Set a breakpoint in a control method at the specified - * AML offset - * - ******************************************************************************/ - -void -acpi_db_set_method_breakpoint ( - NATIVE_CHAR *location, - acpi_walk_state *walk_state, - acpi_parse_object *op) -{ - u32 address; - - - if (!op) { - acpi_os_printf ("There is no method currently executing\n"); - return; - } - - /* Get and verify the breakpoint address */ - - address = ACPI_STRTOUL (location, NULL, 16); - if (address <= op->common.aml_offset) { - acpi_os_printf ("Breakpoint %X is beyond current address %X\n", address, op->common.aml_offset); - } - - /* Save breakpoint in current walk */ - - walk_state->user_breakpoint = address; - acpi_os_printf ("Breakpoint set at AML offset %X\n", address); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_set_method_call_breakpoint - * - * PARAMETERS: Op - Current Op (from parse walk) - * - * RETURN: None - * - * DESCRIPTION: Set a breakpoint in a control method at the specified - * AML offset - * - ******************************************************************************/ - -void -acpi_db_set_method_call_breakpoint ( - acpi_parse_object *op) -{ - - - if (!op) { - acpi_os_printf ("There is no method currently executing\n"); - return; - } - - - acpi_gbl_step_to_next_call = TRUE; -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_disassemble_aml - * - * PARAMETERS: Statements - Number of statements to disassemble - * Op - Current Op (from parse walk) - * - * RETURN: None - * - * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number - * of statements specified. - * - ******************************************************************************/ - -void -acpi_db_disassemble_aml ( - NATIVE_CHAR *statements, - acpi_parse_object *op) -{ - u32 num_statements = 8; - - - if (!op) { - acpi_os_printf ("There is no method currently executing\n"); - return; - } - - if (statements) { - num_statements = ACPI_STRTOUL (statements, NULL, 0); - } - - acpi_dm_disassemble (NULL, op, num_statements); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_dump_namespace - * - * PARAMETERS: Start_arg - Node to begin namespace dump - * Depth_arg - Maximum tree depth to be dumped - * - * RETURN: None - * - * DESCRIPTION: Dump entire namespace or a subtree. Each node is displayed - * with type and other information. - * - ******************************************************************************/ - -void -acpi_db_dump_namespace ( - NATIVE_CHAR *start_arg, - NATIVE_CHAR *depth_arg) -{ - acpi_handle subtree_entry = acpi_gbl_root_node; - u32 max_depth = ACPI_UINT32_MAX; - - - /* No argument given, just start at the root and dump entire namespace */ - - if (start_arg) { - /* Check if numeric argument, must be a Node */ - - if ((start_arg[0] >= 0x30) && (start_arg[0] <= 0x39)) { - subtree_entry = ACPI_TO_POINTER (ACPI_STRTOUL (start_arg, NULL, 16)); - if (!acpi_os_readable (subtree_entry, sizeof (acpi_namespace_node))) { - acpi_os_printf ("Address %p is invalid in this address space\n", subtree_entry); - return; - } - - if (ACPI_GET_DESCRIPTOR_TYPE (subtree_entry) != ACPI_DESC_TYPE_NAMED) { - acpi_os_printf ("Address %p is not a valid Named object\n", subtree_entry); - return; - } - } - - /* Alpha argument */ - - else { - /* The parameter is a name string that must be resolved to a Named obj*/ - - subtree_entry = acpi_db_local_ns_lookup (start_arg); - if (!subtree_entry) { - subtree_entry = acpi_gbl_root_node; - } - } - - /* Now we can check for the depth argument */ - - if (depth_arg) { - max_depth = ACPI_STRTOUL (depth_arg, NULL, 0); - } - } - - acpi_db_set_output_destination (ACPI_DB_DUPLICATE_OUTPUT); - acpi_os_printf ("ACPI Namespace (from %p subtree):\n", subtree_entry); - - /* Display the subtree */ - - acpi_db_set_output_destination (ACPI_DB_REDIRECTABLE_OUTPUT); - acpi_ns_dump_objects (ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth, ACPI_UINT32_MAX, subtree_entry); - acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_dump_namespace_by_owner - * - * PARAMETERS: Owner_arg - Owner ID whose nodes will be displayed - * Depth_arg - Maximum tree depth to be dumped - * - * RETURN: None - * - * DESCRIPTION: Dump elements of the namespace that are owned by the Owner_id. - * - ******************************************************************************/ - -void -acpi_db_dump_namespace_by_owner ( - NATIVE_CHAR *owner_arg, - NATIVE_CHAR *depth_arg) -{ - acpi_handle subtree_entry = acpi_gbl_root_node; - u32 max_depth = ACPI_UINT32_MAX; - u16 owner_id; - - - owner_id = (u16) ACPI_STRTOUL (owner_arg, NULL, 0); - - /* Now we can check for the depth argument */ - - if (depth_arg) { - max_depth = ACPI_STRTOUL (depth_arg, NULL, 0); - } - - acpi_db_set_output_destination (ACPI_DB_DUPLICATE_OUTPUT); - acpi_os_printf ("ACPI Namespace by owner %X:\n", owner_id); - - /* Display the subtree */ - - acpi_db_set_output_destination (ACPI_DB_REDIRECTABLE_OUTPUT); - acpi_ns_dump_objects (ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth, owner_id, subtree_entry); - acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_send_notify - * - * PARAMETERS: Name - Name of ACPI object to send the notify to - * Value - Value of the notify to send. - * - * RETURN: None - * - * DESCRIPTION: Send an ACPI notification. The value specified is sent to the - * named object as an ACPI notify. - * - ******************************************************************************/ - -void -acpi_db_send_notify ( - NATIVE_CHAR *name, - u32 value) -{ - acpi_namespace_node *node; - acpi_status status; - - - /* Translate name to an Named object */ - - node = acpi_db_local_ns_lookup (name); - if (!node) { - return; - } - - /* Decode Named object type */ - - switch (node->type) { - case ACPI_TYPE_DEVICE: - case ACPI_TYPE_THERMAL: - - /* Send the notify */ - - status = acpi_ev_queue_notify_request (node, value); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Could not queue notify\n"); - } - break; - - default: - acpi_os_printf ("Named object is not a device or a thermal object\n"); - break; - } - -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_set_method_data - * - * PARAMETERS: Type_arg - L for local, A for argument - * Index_arg - which one - * Value_arg - Value to set. - * - * RETURN: None - * - * DESCRIPTION: Set a local or argument for the running control method. - * NOTE: only object supported is Number. - * - ******************************************************************************/ - -void -acpi_db_set_method_data ( - NATIVE_CHAR *type_arg, - NATIVE_CHAR *index_arg, - NATIVE_CHAR *value_arg) -{ - NATIVE_CHAR type; - u32 index; - u32 value; - acpi_walk_state *walk_state; - acpi_operand_object *obj_desc; - acpi_status status; - - - /* Validate Type_arg */ - - ACPI_STRUPR (type_arg); - type = type_arg[0]; - if ((type != 'L') && - (type != 'A')) { - acpi_os_printf ("Invalid SET operand: %s\n", type_arg); - return; - } - - /* Get the index and value */ - - index = ACPI_STRTOUL (index_arg, NULL, 16); - value = ACPI_STRTOUL (value_arg, NULL, 16); - - walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); - if (!walk_state) { - acpi_os_printf ("There is no method currently executing\n"); - return; - } - - - /* Create and initialize the new object */ - - obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); - if (!obj_desc) { - acpi_os_printf ("Could not create an internal object\n"); - return; - } - - obj_desc->integer.value = value; - - - /* Store the new object into the target */ - - switch (type) { - case 'A': - - /* Set a method argument */ - - if (index > MTH_MAX_ARG) { - acpi_os_printf ("Arg%d - Invalid argument name\n", index); - return; - } - - status = acpi_ds_store_object_to_local (AML_ARG_OP, index, obj_desc, walk_state); - if (ACPI_FAILURE (status)) { - return; - } - - obj_desc = walk_state->arguments[index].object; - - acpi_os_printf ("Arg%d: ", index); - acpi_db_display_internal_object (obj_desc, walk_state); - break; - - case 'L': - - /* Set a method local */ - - if (index > MTH_MAX_LOCAL) { - acpi_os_printf ("Local%d - Invalid local variable name\n", index); - return; - } - - status = acpi_ds_store_object_to_local (AML_LOCAL_OP, index, obj_desc, walk_state); - if (ACPI_FAILURE (status)) { - return; - } - - obj_desc = walk_state->local_variables[index].object; - - acpi_os_printf ("Local%d: ", index); - acpi_db_display_internal_object (obj_desc, walk_state); - break; - - default: - break; - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_walk_for_specific_objects - * - * PARAMETERS: Callback from Walk_namespace - * - * RETURN: Status - * - * DESCRIPTION: Display short info about objects in the namespace - * - ******************************************************************************/ - -acpi_status -acpi_db_walk_for_specific_objects ( - acpi_handle obj_handle, - u32 nesting_level, - void *context, - void **return_value) -{ - acpi_operand_object *obj_desc; - acpi_status status; - acpi_buffer buffer; - - - obj_desc = acpi_ns_get_attached_object ((acpi_namespace_node *) obj_handle); - - /* Get and display the full pathname to this object */ - - buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_ns_handle_to_pathname (obj_handle, &buffer); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Could Not get pathname for object %p\n", obj_handle); - return (AE_OK); - } - - acpi_os_printf ("%32s", buffer.pointer); - ACPI_MEM_FREE (buffer.pointer); - - - /* Display short information about the object */ - - if (obj_desc) { - switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { - case ACPI_TYPE_METHOD: - acpi_os_printf (" #Args %d Concurrency %X", obj_desc->method.param_count, obj_desc->method.concurrency); - break; - - case ACPI_TYPE_INTEGER: - acpi_os_printf (" Value %X", obj_desc->integer.value); - break; - - case ACPI_TYPE_STRING: - acpi_os_printf (" \"%s\"", obj_desc->string.pointer); - break; - - case ACPI_TYPE_REGION: - acpi_os_printf (" Space_id %X Address %X Length %X", obj_desc->region.space_id, obj_desc->region.address, obj_desc->region.length); - break; - - case ACPI_TYPE_PACKAGE: - acpi_os_printf (" #Elements %X", obj_desc->package.count); - break; - - case ACPI_TYPE_BUFFER: - acpi_os_printf (" Length %X", obj_desc->buffer.length); - break; - - default: - /* Ignore other object types */ - break; - } - } - - acpi_os_printf ("\n"); - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_display_objects - * - * PARAMETERS: Obj_type_arg - Type of object to display - * Display_count_arg - Max depth to display - * - * RETURN: None - * - * DESCRIPTION: Display objects in the namespace of the requested type - * - ******************************************************************************/ - -acpi_status -acpi_db_display_objects ( - NATIVE_CHAR *obj_type_arg, - NATIVE_CHAR *display_count_arg) -{ - acpi_object_type type; - - - /* Get the object type */ - - type = acpi_db_match_argument (obj_type_arg, acpi_db_object_types); - if (type == ACPI_TYPE_NOT_FOUND) { - acpi_os_printf ("Invalid or unsupported argument\n"); - return (AE_OK); - } - - acpi_db_set_output_destination (ACPI_DB_DUPLICATE_OUTPUT); - acpi_os_printf ("Objects of type [%s] defined in the current ACPI Namespace: \n", - acpi_ut_get_type_name (type)); - - acpi_db_set_output_destination (ACPI_DB_REDIRECTABLE_OUTPUT); - - /* Walk the namespace from the root */ - - (void) acpi_walk_namespace (type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - acpi_db_walk_for_specific_objects, (void *) &type, NULL); - - acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_walk_and_match_name - * - * PARAMETERS: Callback from Walk_namespace - * - * RETURN: Status - * - * DESCRIPTION: Find a particular name/names within the namespace. Wildcards - * are supported -- '?' matches any character. - * - ******************************************************************************/ - -acpi_status -acpi_db_walk_and_match_name ( - acpi_handle obj_handle, - u32 nesting_level, - void *context, - void **return_value) -{ - acpi_status status; - NATIVE_CHAR *requested_name = (NATIVE_CHAR *) context; - u32 i; - acpi_buffer buffer; - - - /* Check for a name match */ - - for (i = 0; i < 4; i++) { - /* Wildcard support */ - - if ((requested_name[i] != '?') && - (requested_name[i] != ((acpi_namespace_node *) obj_handle)->name.ascii[i])) { - /* No match, just exit */ - - return (AE_OK); - } - } - - - /* Get the full pathname to this object */ - - buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_ns_handle_to_pathname (obj_handle, &buffer); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Could Not get pathname for object %p\n", obj_handle); - } - else { - acpi_os_printf ("%32s (%p) - %s\n", buffer.pointer, obj_handle, - acpi_ut_get_type_name (((acpi_namespace_node *) obj_handle)->type)); - ACPI_MEM_FREE (buffer.pointer); - } - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_find_name_in_namespace - * - * PARAMETERS: Name_arg - The 4-character ACPI name to find. - * wildcards are supported. - * - * RETURN: None - * - * DESCRIPTION: Search the namespace for a given name (with wildcards) - * - ******************************************************************************/ - -acpi_status -acpi_db_find_name_in_namespace ( - NATIVE_CHAR *name_arg) -{ - - if (ACPI_STRLEN (name_arg) > 4) { - acpi_os_printf ("Name must be no longer than 4 characters\n"); - return (AE_OK); - } - - /* Walk the namespace from the root */ - - (void) acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - acpi_db_walk_and_match_name, name_arg, NULL); - - acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_set_scope - * - * PARAMETERS: Name - New scope path - * - * RETURN: Status - * - * DESCRIPTION: Set the "current scope" as maintained by this utility. - * The scope is used as a prefix to ACPI paths. - * - ******************************************************************************/ - -void -acpi_db_set_scope ( - NATIVE_CHAR *name) -{ - acpi_status status; - acpi_namespace_node *node; - - - if (!name || name[0] == 0) { - acpi_os_printf ("Current scope: %s\n", acpi_gbl_db_scope_buf); - return; - } - - acpi_db_prep_namestring (name); - - - if (name[0] == '\\') { - /* Validate new scope from the root */ - - status = acpi_ns_get_node_by_path (name, acpi_gbl_root_node, ACPI_NS_NO_UPSEARCH, &node); - if (ACPI_FAILURE (status)) { - goto error_exit; - } - - ACPI_STRCPY (acpi_gbl_db_scope_buf, name); - ACPI_STRCAT (acpi_gbl_db_scope_buf, "\\"); - } - else { - /* Validate new scope relative to old scope */ - - status = acpi_ns_get_node_by_path (name, acpi_gbl_db_scope_node, ACPI_NS_NO_UPSEARCH, &node); - if (ACPI_FAILURE (status)) { - goto error_exit; - } - - ACPI_STRCAT (acpi_gbl_db_scope_buf, name); - ACPI_STRCAT (acpi_gbl_db_scope_buf, "\\"); - } - - acpi_gbl_db_scope_node = node; - acpi_os_printf ("New scope: %s\n", acpi_gbl_db_scope_buf); - return; - - -error_exit: - - acpi_os_printf ("Could not attach scope: %s, %s\n", name, acpi_format_exception (status)); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_display_resources - * - * PARAMETERS: Object_arg - String with hex value of the object - * - * RETURN: None - * - * DESCRIPTION: - * - ******************************************************************************/ - -void -acpi_db_display_resources ( - NATIVE_CHAR *object_arg) -{ -#if ACPI_MACHINE_WIDTH != 16 - - acpi_operand_object *obj_desc; - acpi_status status; - acpi_buffer return_obj; - - - acpi_db_set_output_destination (ACPI_DB_REDIRECTABLE_OUTPUT); - acpi_dbg_level |= ACPI_LV_RESOURCES; - - /* Convert string to object pointer */ - - obj_desc = ACPI_TO_POINTER (ACPI_STRTOUL (object_arg, NULL, 16)); - - /* Prepare for a return object of arbitrary size */ - - return_obj.pointer = acpi_gbl_db_buffer; - return_obj.length = ACPI_DEBUG_BUFFER_SIZE; - - /* _PRT */ - - acpi_os_printf ("Evaluating _PRT\n"); - - status = acpi_evaluate_object (obj_desc, "_PRT", NULL, &return_obj); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Could not obtain _PRT: %s\n", acpi_format_exception (status)); - goto get_crs; - } - - return_obj.pointer = acpi_gbl_db_buffer; - return_obj.length = ACPI_DEBUG_BUFFER_SIZE; - - status = acpi_get_irq_routing_table (obj_desc, &return_obj); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Get_irq_routing_table failed: %s\n", acpi_format_exception (status)); - } - - else { - acpi_rs_dump_irq_list ((u8 *) acpi_gbl_db_buffer); - } - - - /* _CRS */ - -get_crs: - acpi_os_printf ("Evaluating _CRS\n"); - - return_obj.pointer = acpi_gbl_db_buffer; - return_obj.length = ACPI_DEBUG_BUFFER_SIZE; - - status = acpi_evaluate_object (obj_desc, "_CRS", NULL, &return_obj); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Could not obtain _CRS: %s\n", acpi_format_exception (status)); - goto get_prs; - } - - return_obj.pointer = acpi_gbl_db_buffer; - return_obj.length = ACPI_DEBUG_BUFFER_SIZE; - - status = acpi_get_current_resources (obj_desc, &return_obj); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Acpi_get_current_resources failed: %s\n", acpi_format_exception (status)); - goto get_prs; - } - - else { - acpi_rs_dump_resource_list (ACPI_CAST_PTR (acpi_resource, acpi_gbl_db_buffer)); - } - - status = acpi_set_current_resources (obj_desc, &return_obj); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Acpi_set_current_resources failed: %s\n", acpi_format_exception (status)); - goto get_prs; - } - - - /* _PRS */ - -get_prs: - acpi_os_printf ("Evaluating _PRS\n"); - - return_obj.pointer = acpi_gbl_db_buffer; - return_obj.length = ACPI_DEBUG_BUFFER_SIZE; - - status = acpi_evaluate_object (obj_desc, "_PRS", NULL, &return_obj); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Could not obtain _PRS: %s\n", acpi_format_exception (status)); - goto cleanup; - } - - return_obj.pointer = acpi_gbl_db_buffer; - return_obj.length = ACPI_DEBUG_BUFFER_SIZE; - - status = acpi_get_possible_resources (obj_desc, &return_obj); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Acpi_get_possible_resources failed: %s\n", acpi_format_exception (status)); - } - - else { - acpi_rs_dump_resource_list (ACPI_CAST_PTR (acpi_resource, acpi_gbl_db_buffer)); - } - - -cleanup: - - acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); - return; -#endif - -} - - -typedef struct -{ - u32 nodes; - u32 objects; -} ACPI_INTEGRITY_INFO; - -/******************************************************************************* - * - * FUNCTION: Acpi_db_integrity_walk - * - * PARAMETERS: Callback from Walk_namespace - * - * RETURN: Status - * - * DESCRIPTION: Examine one NS node for valid values. - * - ******************************************************************************/ - -acpi_status -acpi_db_integrity_walk ( - acpi_handle obj_handle, - u32 nesting_level, - void *context, - void **return_value) -{ - ACPI_INTEGRITY_INFO *info = (ACPI_INTEGRITY_INFO *) context; - acpi_namespace_node *node = (acpi_namespace_node *) obj_handle; - acpi_operand_object *object; - - - info->nodes++; - if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) { - acpi_os_printf ("Invalid Descriptor Type for Node %p, Type = %X\n", - node, ACPI_GET_DESCRIPTOR_TYPE (node)); - } - - if (node->type > INTERNAL_TYPE_MAX) { - acpi_os_printf ("Invalid Object Type for Node %p, Type = %X\n", - node, node->type); - } - - if (!acpi_ut_valid_acpi_name (node->name.integer)) { - acpi_os_printf ("Invalid Acpi_name for Node %p\n", node); - } - - object = acpi_ns_get_attached_object (node); - if (object) { - info->objects++; - if (ACPI_GET_DESCRIPTOR_TYPE (object) != ACPI_DESC_TYPE_OPERAND) { - acpi_os_printf ("Invalid Descriptor Type for Object %p, Type = %X\n", - object, ACPI_GET_DESCRIPTOR_TYPE (object)); - } - } - - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_check_integrity - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Check entire namespace for data structure integrity - * - ******************************************************************************/ - -void -acpi_db_check_integrity (void) -{ - ACPI_INTEGRITY_INFO info = {0,0}; - - /* Search all nodes in namespace */ - - (void) acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - acpi_db_integrity_walk, (void *) &info, NULL); - - acpi_os_printf ("Verified %d namespace nodes with %d Objects\n", info.nodes, info.objects); - -} - -#endif /* ACPI_DEBUGGER */ diff --git a/drivers/acpi/debugger/dbdisply.c b/drivers/acpi/debugger/dbdisply.c deleted file mode 100644 index 61c55d28a531..000000000000 --- a/drivers/acpi/debugger/dbdisply.c +++ /dev/null @@ -1,859 +0,0 @@ -/******************************************************************************* - * - * Module Name: dbdisply - debug display commands - * $Revision: 78 $ - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2002, R. Byron Moore - * - * 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 "acpi.h" -#include "amlcode.h" -#include "acdispat.h" -#include "acnamesp.h" -#include "acparser.h" -#include "acinterp.h" -#include "acdebug.h" - - -#ifdef ACPI_DEBUGGER - - -#define _COMPONENT ACPI_CA_DEBUGGER - ACPI_MODULE_NAME ("dbdisply") - - -/****************************************************************************** - * - * FUNCTION: Acpi_db_get_pointer - * - * PARAMETERS: Target - Pointer to string to be converted - * - * RETURN: Converted pointer - * - * DESCRIPTION: Convert an ascii pointer value to a real value - * - *****************************************************************************/ - -void * -acpi_db_get_pointer ( - void *target) -{ - void *obj_ptr; - - -#if ACPI_MACHINE_WIDTH == 16 -#include <stdio.h> - - /* Have to handle 16-bit pointers of the form segment:offset */ - - if (!sscanf (target, "%p", &obj_ptr)) { - acpi_os_printf ("Invalid pointer: %s\n", target); - return (NULL); - } - -#else - - /* Simple flat pointer */ - - obj_ptr = ACPI_TO_POINTER (ACPI_STRTOUL (target, NULL, 16)); -#endif - - return (obj_ptr); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_dump_parser_descriptor - * - * PARAMETERS: Op - A parser Op descriptor - * - * RETURN: None - * - * DESCRIPTION: Display a formatted parser object - * - ******************************************************************************/ - -void -acpi_db_dump_parser_descriptor ( - acpi_parse_object *op) -{ - const acpi_opcode_info *info; - - - info = acpi_ps_get_opcode_info (op->common.aml_opcode); - - acpi_os_printf ("Parser Op Descriptor:\n"); - acpi_os_printf ("%20.20s : %4.4X\n", "Opcode", op->common.aml_opcode); - - ACPI_DEBUG_ONLY_MEMBERS (acpi_os_printf ("%20.20s : %s\n", "Opcode Name", info->name)); - - acpi_os_printf ("%20.20s : %p\n", "Value/Arg_list", op->common.value.arg); - acpi_os_printf ("%20.20s : %p\n", "Parent", op->common.parent); - acpi_os_printf ("%20.20s : %p\n", "Next_op", op->common.next); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_decode_and_display_object - * - * PARAMETERS: Target - String with object to be displayed. Names - * and hex pointers are supported. - * Output_type - Byte, Word, Dword, or Qword (B|W|D|Q) - * - * RETURN: None - * - * DESCRIPTION: Display a formatted ACPI object - * - ******************************************************************************/ - -void -acpi_db_decode_and_display_object ( - NATIVE_CHAR *target, - NATIVE_CHAR *output_type) -{ - void *obj_ptr; - acpi_namespace_node *node; - acpi_operand_object *obj_desc; - u32 display = DB_BYTE_DISPLAY; - NATIVE_CHAR buffer[80]; - acpi_buffer ret_buf; - acpi_status status; - u32 size; - - - if (!target) { - return; - } - - /* Decode the output type */ - - if (output_type) { - ACPI_STRUPR (output_type); - if (output_type[0] == 'W') { - display = DB_WORD_DISPLAY; - } - else if (output_type[0] == 'D') { - display = DB_DWORD_DISPLAY; - } - else if (output_type[0] == 'Q') { - display = DB_QWORD_DISPLAY; - } - } - - ret_buf.length = sizeof (buffer); - ret_buf.pointer = buffer; - - /* Differentiate between a number and a name */ - - if ((target[0] >= 0x30) && (target[0] <= 0x39)) { - obj_ptr = acpi_db_get_pointer (target); - if (!acpi_os_readable (obj_ptr, 16)) { - acpi_os_printf ("Address %p is invalid in this address space\n", obj_ptr); - return; - } - - /* Decode the object type */ - - switch (ACPI_GET_DESCRIPTOR_TYPE (obj_ptr)) { - case ACPI_DESC_TYPE_NAMED: - - /* This is a namespace Node */ - - if (!acpi_os_readable (obj_ptr, sizeof (acpi_namespace_node))) { - acpi_os_printf ("Cannot read entire Named object at address %p\n", obj_ptr); - return; - } - - node = obj_ptr; - goto dump_nte; - - - case ACPI_DESC_TYPE_OPERAND: - - /* This is a ACPI OPERAND OBJECT */ - - if (!acpi_os_readable (obj_ptr, sizeof (acpi_operand_object))) { - acpi_os_printf ("Cannot read entire ACPI object at address %p\n", obj_ptr); - return; - } - - acpi_ut_dump_buffer (obj_ptr, sizeof (acpi_operand_object), display, ACPI_UINT32_MAX); - acpi_ex_dump_object_descriptor (obj_ptr, 1); - break; - - - case ACPI_DESC_TYPE_PARSER: - - /* This is a Parser Op object */ - - if (!acpi_os_readable (obj_ptr, sizeof (acpi_parse_object))) { - acpi_os_printf ("Cannot read entire Parser object at address %p\n", obj_ptr); - return; - } - - acpi_ut_dump_buffer (obj_ptr, sizeof (acpi_parse_object), display, ACPI_UINT32_MAX); - acpi_db_dump_parser_descriptor ((acpi_parse_object *) obj_ptr); - break; - - - default: - - /* Is not a recognizeable object */ - - size = 16; - if (acpi_os_readable (obj_ptr, 64)) { - size = 64; - } - - /* Just dump some memory */ - - acpi_ut_dump_buffer (obj_ptr, size, display, ACPI_UINT32_MAX); - break; - } - - return; - } - - /* The parameter is a name string that must be resolved to a Named obj */ - - node = acpi_db_local_ns_lookup (target); - if (!node) { - return; - } - - -dump_nte: - /* Now dump the Named obj */ - - status = acpi_get_name (node, ACPI_FULL_PATHNAME, &ret_buf); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Could not convert name to pathname\n"); - } - - else { - acpi_os_printf ("Object (%p) Pathname: %s\n", node, ret_buf.pointer); - } - - if (!acpi_os_readable (node, sizeof (acpi_namespace_node))) { - acpi_os_printf ("Invalid Named object at address %p\n", node); - return; - } - - acpi_ut_dump_buffer ((void *) node, sizeof (acpi_namespace_node), display, ACPI_UINT32_MAX); - acpi_ex_dump_node (node, 1); - - obj_desc = acpi_ns_get_attached_object (node); - if (obj_desc) { - acpi_os_printf ("\nAttached Object (%p):\n", obj_desc); - if (!acpi_os_readable (obj_desc, sizeof (acpi_operand_object))) { - acpi_os_printf ("Invalid internal ACPI Object at address %p\n", obj_desc); - return; - } - - acpi_ut_dump_buffer ((void *) obj_desc, sizeof (acpi_operand_object), display, ACPI_UINT32_MAX); - acpi_ex_dump_object_descriptor (obj_desc, 1); - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_decode_internal_object - * - * PARAMETERS: Obj_desc - Object to be displayed - * - * RETURN: None - * - * DESCRIPTION: Short display of an internal object. Numbers and Strings. - * - ******************************************************************************/ - -void -acpi_db_decode_internal_object ( - acpi_operand_object *obj_desc) -{ - u32 i; - - - if (!obj_desc) { - acpi_os_printf (" Uninitialized\n"); - return; - } - - if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) { - acpi_os_printf ("%p", obj_desc); - return; - } - - acpi_os_printf (" %s", acpi_ut_get_object_type_name (obj_desc)); - - switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { - case ACPI_TYPE_INTEGER: - - acpi_os_printf (" %8.8X%8.8X", ACPI_HIDWORD (obj_desc->integer.value), - ACPI_LODWORD (obj_desc->integer.value)); - break; - - - case ACPI_TYPE_STRING: - - acpi_os_printf ("(%d) \"%.24s", - obj_desc->string.length, obj_desc->string.pointer); - - if (obj_desc->string.length > 24) - { - acpi_os_printf ("..."); - } - else - { - acpi_os_printf ("\""); - } - break; - - - case ACPI_TYPE_BUFFER: - - acpi_os_printf ("(%d)", obj_desc->buffer.length); - for (i = 0; (i < 8) && (i < obj_desc->buffer.length); i++) { - acpi_os_printf (" %2.2X", obj_desc->buffer.pointer[i]); - } - break; - - - default: - - acpi_os_printf ("%p", obj_desc); - break; - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_decode_node - * - * PARAMETERS: Node - Object to be displayed - * - * RETURN: None - * - * DESCRIPTION: Short display of a namespace node - * - ******************************************************************************/ - -void -acpi_db_decode_node ( - acpi_namespace_node *node) -{ - - - acpi_os_printf ("<Node> Name %4.4s Type-%s", - node->name.ascii, acpi_ut_get_type_name (node->type)); - - if (node->flags & ANOBJ_METHOD_ARG) { - acpi_os_printf (" [Method Arg]"); - } - if (node->flags & ANOBJ_METHOD_LOCAL) { - acpi_os_printf (" [Method Local]"); - } - - acpi_db_decode_internal_object (acpi_ns_get_attached_object (node)); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_display_internal_object - * - * PARAMETERS: Obj_desc - Object to be displayed - * Walk_state - Current walk state - * - * RETURN: None - * - * DESCRIPTION: Short display of an internal object - * - ******************************************************************************/ - -void -acpi_db_display_internal_object ( - acpi_operand_object *obj_desc, - acpi_walk_state *walk_state) -{ - u8 type; - - - acpi_os_printf ("%p ", obj_desc); - - if (!obj_desc) { - acpi_os_printf ("<Null_obj>\n"); - return; - } - - /* Decode the object type */ - - switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) { - case ACPI_DESC_TYPE_PARSER: - - acpi_os_printf ("<Parser> "); - break; - - - case ACPI_DESC_TYPE_NAMED: - - acpi_db_decode_node ((acpi_namespace_node *) obj_desc); - break; - - - case ACPI_DESC_TYPE_OPERAND: - - type = ACPI_GET_OBJECT_TYPE (obj_desc); - if (type > INTERNAL_TYPE_MAX) { - acpi_os_printf (" Type %hX [Invalid Type]", type); - return; - } - - /* Decode the ACPI object type */ - - switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { - case INTERNAL_TYPE_REFERENCE: - - switch (obj_desc->reference.opcode) { - case AML_LOCAL_OP: - - acpi_os_printf ("[Local%d] ", obj_desc->reference.offset); - if (walk_state) { - obj_desc = walk_state->local_variables[obj_desc->reference.offset].object; - acpi_os_printf ("%p", obj_desc); - acpi_db_decode_internal_object (obj_desc); - } - break; - - - case AML_ARG_OP: - - acpi_os_printf ("[Arg%d] ", obj_desc->reference.offset); - if (walk_state) { - obj_desc = walk_state->arguments[obj_desc->reference.offset].object; - acpi_os_printf ("%p", obj_desc); - acpi_db_decode_internal_object (obj_desc); - } - break; - - - case AML_DEBUG_OP: - - acpi_os_printf ("[Debug] "); - break; - - - case AML_INDEX_OP: - - acpi_os_printf ("[Index] "); - acpi_db_decode_internal_object (obj_desc->reference.object); - break; - - - case AML_REF_OF_OP: - - acpi_os_printf ("[Reference] "); - - /* Reference can be to a Node or an Operand object */ - - switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc->reference.object)) { - case ACPI_DESC_TYPE_NAMED: - acpi_db_decode_node (obj_desc->reference.object); - break; - - case ACPI_DESC_TYPE_OPERAND: - acpi_db_decode_internal_object (obj_desc->reference.object); - break; - - default: - break; - } - break; - - - default: - - acpi_os_printf ("Unknown Reference opcode %X\n", - obj_desc->reference.opcode); - break; - } - break; - - default: - - acpi_os_printf ("<Obj> "); - acpi_os_printf (" "); - acpi_db_decode_internal_object (obj_desc); - break; - } - break; - - - default: - - acpi_os_printf ("<Not a valid ACPI Object Descriptor> "); - break; - } - - acpi_os_printf ("\n"); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_display_method_info - * - * PARAMETERS: Start_op - Root of the control method parse tree - * - * RETURN: None - * - * DESCRIPTION: Display information about the current method - * - ******************************************************************************/ - -void -acpi_db_display_method_info ( - acpi_parse_object *start_op) -{ - acpi_walk_state *walk_state; - acpi_operand_object *obj_desc; - acpi_namespace_node *node; - acpi_parse_object *root_op; - acpi_parse_object *op; - const acpi_opcode_info *op_info; - u32 num_ops = 0; - u32 num_operands = 0; - u32 num_operators = 0; - u32 num_remaining_ops = 0; - u32 num_remaining_operands = 0; - u32 num_remaining_operators = 0; - u32 num_args; - u32 concurrency; - u8 count_remaining = FALSE; - - - walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); - if (!walk_state) { - acpi_os_printf ("There is no method currently executing\n"); - return; - } - - obj_desc = walk_state->method_desc; - node = walk_state->method_node; - - num_args = obj_desc->method.param_count; - concurrency = obj_desc->method.concurrency; - - acpi_os_printf ("Currently executing control method is [%4.4s]\n", node->name.ascii); - acpi_os_printf ("%X arguments, max concurrency = %X\n", num_args, concurrency); - - - root_op = start_op; - while (root_op->common.parent) { - root_op = root_op->common.parent; - } - - op = root_op; - - while (op) { - if (op == start_op) { - count_remaining = TRUE; - } - - num_ops++; - if (count_remaining) { - num_remaining_ops++; - } - - /* Decode the opcode */ - - op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); - switch (op_info->class) { - case AML_CLASS_ARGUMENT: - if (count_remaining) { - num_remaining_operands++; - } - - num_operands++; - break; - - case AML_CLASS_UNKNOWN: - /* Bad opcode or ASCII character */ - - continue; - - default: - if (count_remaining) { - num_remaining_operators++; - } - - num_operators++; - break; - } - - op = acpi_ps_get_depth_next (start_op, op); - } - - acpi_os_printf ("Method contains: %X AML Opcodes - %X Operators, %X Operands\n", - num_ops, num_operators, num_operands); - - acpi_os_printf ("Remaining to execute: %X AML Opcodes - %X Operators, %X Operands\n", - num_remaining_ops, num_remaining_operators, num_remaining_operands); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_display_locals - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Display all locals for the currently running control method - * - ******************************************************************************/ - -void -acpi_db_display_locals (void) -{ - u32 i; - acpi_walk_state *walk_state; - acpi_operand_object *obj_desc; - acpi_namespace_node *node; - - - walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); - if (!walk_state) { - acpi_os_printf ("There is no method currently executing\n"); - return; - } - - obj_desc = walk_state->method_desc; - node = walk_state->method_node; - acpi_os_printf ("Local Variables for method [%4.4s]:\n", node->name.ascii); - - for (i = 0; i < MTH_NUM_LOCALS; i++) { - obj_desc = walk_state->local_variables[i].object; - acpi_os_printf ("Local%d: ", i); - acpi_db_display_internal_object (obj_desc, walk_state); - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_display_arguments - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Display all arguments for the currently running control method - * - ******************************************************************************/ - -void -acpi_db_display_arguments (void) -{ - u32 i; - acpi_walk_state *walk_state; - acpi_operand_object *obj_desc; - u32 num_args; - u32 concurrency; - acpi_namespace_node *node; - - - walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); - if (!walk_state) { - acpi_os_printf ("There is no method currently executing\n"); - return; - } - - obj_desc = walk_state->method_desc; - node = walk_state->method_node; - - num_args = obj_desc->method.param_count; - concurrency = obj_desc->method.concurrency; - - acpi_os_printf ("Method [%4.4s] has %X arguments, max concurrency = %X\n", - node->name.ascii, num_args, concurrency); - - for (i = 0; i < num_args; i++) { - obj_desc = walk_state->arguments[i].object; - acpi_os_printf ("Arg%d: ", i); - acpi_db_display_internal_object (obj_desc, walk_state); - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_display_results - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Display current contents of a method result stack - * - ******************************************************************************/ - -void -acpi_db_display_results (void) -{ - u32 i; - acpi_walk_state *walk_state; - acpi_operand_object *obj_desc; - u32 num_results = 0; - acpi_namespace_node *node; - - - walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); - if (!walk_state) { - acpi_os_printf ("There is no method currently executing\n"); - return; - } - - obj_desc = walk_state->method_desc; - node = walk_state->method_node; - - if (walk_state->results) { - num_results = walk_state->results->results.num_results; - } - - acpi_os_printf ("Method [%4.4s] has %X stacked result objects\n", - node->name.ascii, num_results); - - for (i = 0; i < num_results; i++) { - obj_desc = walk_state->results->results.obj_desc[i]; - acpi_os_printf ("Result%d: ", i); - acpi_db_display_internal_object (obj_desc, walk_state); - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_display_calling_tree - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Display current calling tree of nested control methods - * - ******************************************************************************/ - -void -acpi_db_display_calling_tree (void) -{ - acpi_walk_state *walk_state; - acpi_namespace_node *node; - - - walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); - if (!walk_state) { - acpi_os_printf ("There is no method currently executing\n"); - return; - } - - node = walk_state->method_node; - acpi_os_printf ("Current Control Method Call Tree\n"); - - while (walk_state) { - node = walk_state->method_node; - - acpi_os_printf (" [%4.4s]\n", node->name.ascii); - - walk_state = walk_state->next; - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_display_result_object - * - * PARAMETERS: Obj_desc - Object to be displayed - * Walk_state - Current walk state - * - * RETURN: None - * - * DESCRIPTION: Display the result of an AML opcode - * - * Note: Curently only displays the result object if we are single stepping. - * However, this output may be useful in other contexts and could be enabled - * to do so if needed. - * - ******************************************************************************/ - -void -acpi_db_display_result_object ( - acpi_operand_object *obj_desc, - acpi_walk_state *walk_state) -{ - - /* Only display if single stepping */ - - if (!acpi_gbl_cm_single_step) { - return; - } - - acpi_os_printf ("Result_obj: "); - acpi_db_display_internal_object (obj_desc, walk_state); - acpi_os_printf ("\n"); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_display_argument_object - * - * PARAMETERS: Obj_desc - Object to be displayed - * Walk_state - Current walk state - * - * RETURN: None - * - * DESCRIPTION: Display the result of an AML opcode - * - ******************************************************************************/ - -void -acpi_db_display_argument_object ( - acpi_operand_object *obj_desc, - acpi_walk_state *walk_state) -{ - - if (!acpi_gbl_cm_single_step) { - return; - } - - acpi_os_printf ("Arg_obj: "); - acpi_db_display_internal_object (obj_desc, walk_state); -} - -#endif /* ACPI_DEBUGGER */ - diff --git a/drivers/acpi/debugger/dbexec.c b/drivers/acpi/debugger/dbexec.c deleted file mode 100644 index 9d5b9dd7c05d..000000000000 --- a/drivers/acpi/debugger/dbexec.c +++ /dev/null @@ -1,405 +0,0 @@ -/******************************************************************************* - * - * Module Name: dbexec - debugger control method execution - * $Revision: 44 $ - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2002, R. Byron Moore - * - * 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 "acpi.h" -#include "acdebug.h" - -#ifdef ACPI_DEBUGGER - -#define _COMPONENT ACPI_CA_DEBUGGER - ACPI_MODULE_NAME ("dbexec") - - -static acpi_db_method_info acpi_gbl_db_method_info; - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_execute_method - * - * PARAMETERS: Info - Valid info segment - * Return_obj - Where to put return object - * - * RETURN: Status - * - * DESCRIPTION: Execute a control method. - * - ******************************************************************************/ - -acpi_status -acpi_db_execute_method ( - acpi_db_method_info *info, - acpi_buffer *return_obj) -{ - acpi_status status; - acpi_object_list param_objects; - acpi_object params[MTH_NUM_ARGS]; - u32 i; - - - if (acpi_gbl_db_output_to_file && !acpi_dbg_level) { - acpi_os_printf ("Warning: debug output is not enabled!\n"); - } - - /* Are there arguments to the method? */ - - if (info->args && info->args[0]) { - for (i = 0; info->args[i] && i < MTH_NUM_ARGS; i++) { - params[i].type = ACPI_TYPE_INTEGER; - params[i].integer.value = ACPI_STRTOUL (info->args[i], NULL, 16); - } - - param_objects.pointer = params; - param_objects.count = i; - } - else { - /* Setup default parameters */ - - params[0].type = ACPI_TYPE_INTEGER; - params[0].integer.value = 0x01020304; - - params[1].type = ACPI_TYPE_STRING; - params[1].string.length = 12; - params[1].string.pointer = "AML Debugger"; - - param_objects.pointer = params; - param_objects.count = 2; - } - - /* Prepare for a return object of arbitrary size */ - - return_obj->pointer = acpi_gbl_db_buffer; - return_obj->length = ACPI_DEBUG_BUFFER_SIZE; - - /* Do the actual method execution */ - - status = acpi_evaluate_object (NULL, info->pathname, ¶m_objects, return_obj); - - acpi_gbl_cm_single_step = FALSE; - acpi_gbl_method_executing = FALSE; - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_execute_setup - * - * PARAMETERS: Info - Valid method info - * - * RETURN: Status - * - * DESCRIPTION: Setup info segment prior to method execution - * - ******************************************************************************/ - -void -acpi_db_execute_setup ( - acpi_db_method_info *info) -{ - - /* Catenate the current scope to the supplied name */ - - info->pathname[0] = 0; - if ((info->name[0] != '\\') && - (info->name[0] != '/')) { - ACPI_STRCAT (info->pathname, acpi_gbl_db_scope_buf); - } - - ACPI_STRCAT (info->pathname, info->name); - acpi_db_prep_namestring (info->pathname); - - acpi_db_set_output_destination (ACPI_DB_DUPLICATE_OUTPUT); - acpi_os_printf ("Executing %s\n", info->pathname); - - if (info->flags & EX_SINGLE_STEP) { - acpi_gbl_cm_single_step = TRUE; - acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); - } - - else { - /* No single step, allow redirection to a file */ - - acpi_db_set_output_destination (ACPI_DB_REDIRECTABLE_OUTPUT); - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_get_outstanding_allocations - * - * PARAMETERS: None - * - * RETURN: Current global allocation count minus cache entries - * - * DESCRIPTION: Determine the current number of "outstanding" allocations -- - * those allocations that have not been freed and also are not - * in one of the various object caches. - * - ******************************************************************************/ - -u32 -acpi_db_get_outstanding_allocations ( - void) -{ - u32 outstanding = 0; - -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - u32 i; - - - for (i = ACPI_MEM_LIST_FIRST_CACHE_LIST; i < ACPI_NUM_MEM_LISTS; i++) { - outstanding += (acpi_gbl_memory_lists[i].total_allocated - - acpi_gbl_memory_lists[i].total_freed - - acpi_gbl_memory_lists[i].cache_depth); - } -#endif - - return (outstanding); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_execute - * - * PARAMETERS: Name - Name of method to execute - * Args - Parameters to the method - * Flags - single step/no single step - * - * RETURN: Status - * - * DESCRIPTION: Execute a control method. Name is relative to the current - * scope. - * - ******************************************************************************/ - -void -acpi_db_execute ( - NATIVE_CHAR *name, - NATIVE_CHAR **args, - u32 flags) -{ - acpi_status status; - acpi_buffer return_obj; - - -#ifdef ACPI_DEBUG_OUTPUT - u32 previous_allocations; - u32 allocations; - - - /* Memory allocation tracking */ - - previous_allocations = acpi_db_get_outstanding_allocations (); -#endif - - acpi_gbl_db_method_info.name = name; - acpi_gbl_db_method_info.args = args; - acpi_gbl_db_method_info.flags = flags; - - return_obj.pointer = NULL; - return_obj.length = ACPI_ALLOCATE_BUFFER; - - acpi_db_execute_setup (&acpi_gbl_db_method_info); - status = acpi_db_execute_method (&acpi_gbl_db_method_info, &return_obj); - - /* - * Allow any handlers in separate threads to complete. - * (Such as Notify handlers invoked from AML executed above). - */ - acpi_os_sleep (0, 10); - - -#ifdef ACPI_DEBUG_OUTPUT - - /* Memory allocation tracking */ - - allocations = acpi_db_get_outstanding_allocations () - previous_allocations; - - acpi_db_set_output_destination (ACPI_DB_DUPLICATE_OUTPUT); - - if (allocations > 0) { - acpi_os_printf ("Outstanding: %ld allocations after execution\n", - allocations); - } -#endif - - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Execution of %s failed with status %s\n", - acpi_gbl_db_method_info.pathname, acpi_format_exception (status)); - } - - else { - /* Display a return object, if any */ - - if (return_obj.length) { - acpi_os_printf ("Execution of %s returned object %p Buflen %X\n", - acpi_gbl_db_method_info.pathname, return_obj.pointer, return_obj.length); - acpi_db_dump_object (return_obj.pointer, 1); - } - else { - acpi_os_printf ("No return object from execution of %s\n", - acpi_gbl_db_method_info.pathname); - } - } - - acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_method_thread - * - * PARAMETERS: Context - Execution info segment - * - * RETURN: None - * - * DESCRIPTION: Debugger execute thread. Waits for a command line, then - * simply dispatches it. - * - ******************************************************************************/ - -void ACPI_SYSTEM_XFACE -acpi_db_method_thread ( - void *context) -{ - acpi_status status; - acpi_db_method_info *info = context; - u32 i; - acpi_buffer return_obj; - - - for (i = 0; i < info->num_loops; i++) { - status = acpi_db_execute_method (info, &return_obj); - if (ACPI_SUCCESS (status)) { - if (return_obj.length) { - acpi_os_printf ("Execution of %s returned object %p Buflen %X\n", - info->pathname, return_obj.pointer, return_obj.length); - acpi_db_dump_object (return_obj.pointer, 1); - } - } - } - - /* Signal our completion */ - - status = acpi_os_signal_semaphore (info->thread_gate, 1); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Could not signal debugger semaphore\n"); - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_create_execution_threads - * - * PARAMETERS: Num_threads_arg - Number of threads to create - * Num_loops_arg - Loop count for the thread(s) - * Method_name_arg - Control method to execute - * - * RETURN: None - * - * DESCRIPTION: Create threads to execute method(s) - * - ******************************************************************************/ - -void -acpi_db_create_execution_threads ( - NATIVE_CHAR *num_threads_arg, - NATIVE_CHAR *num_loops_arg, - NATIVE_CHAR *method_name_arg) -{ - acpi_status status; - u32 num_threads; - u32 num_loops; - u32 i; - acpi_handle thread_gate; - - - /* Get the arguments */ - - num_threads = ACPI_STRTOUL (num_threads_arg, NULL, 0); - num_loops = ACPI_STRTOUL (num_loops_arg, NULL, 0); - - if (!num_threads || !num_loops) { - acpi_os_printf ("Bad argument: Threads %X, Loops %X\n", num_threads, num_loops); - return; - } - - /* Create the synchronization semaphore */ - - status = acpi_os_create_semaphore (1, 0, &thread_gate); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Could not create semaphore, %s\n", acpi_format_exception (status)); - return; - } - - /* Setup the context to be passed to each thread */ - - acpi_gbl_db_method_info.name = method_name_arg; - acpi_gbl_db_method_info.args = NULL; - acpi_gbl_db_method_info.flags = 0; - acpi_gbl_db_method_info.num_loops = num_loops; - acpi_gbl_db_method_info.thread_gate = thread_gate; - - acpi_db_execute_setup (&acpi_gbl_db_method_info); - - /* Create the threads */ - - acpi_os_printf ("Creating %X threads to execute %X times each\n", num_threads, num_loops); - - for (i = 0; i < (num_threads); i++) { - status = acpi_os_queue_for_execution (OSD_PRIORITY_MED, acpi_db_method_thread, &acpi_gbl_db_method_info); - if (ACPI_FAILURE (status)) { - break; - } - } - - /* Wait for all threads to complete */ - - i = num_threads; - while (i) /* Brain damage for OSD implementations that only support wait of 1 unit */ { - status = acpi_os_wait_semaphore (thread_gate, 1, WAIT_FOREVER); - i--; - } - - /* Cleanup and exit */ - - (void) acpi_os_delete_semaphore (thread_gate); - - acpi_db_set_output_destination (ACPI_DB_DUPLICATE_OUTPUT); - acpi_os_printf ("All threads (%X) have completed\n", num_threads); - acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); -} - - -#endif /* ACPI_DEBUGGER */ - - diff --git a/drivers/acpi/debugger/dbfileio.c b/drivers/acpi/debugger/dbfileio.c deleted file mode 100644 index 79e8b92843b5..000000000000 --- a/drivers/acpi/debugger/dbfileio.c +++ /dev/null @@ -1,399 +0,0 @@ -/******************************************************************************* - * - * Module Name: dbfileio - Debugger file I/O commands. These can't usually - * be used when running the debugger in Ring 0 (Kernel mode) - * $Revision: 68 $ - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2002, R. Byron Moore - * - * 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 "acpi.h" -#include "acdebug.h" -#include "acnamesp.h" -#include "actables.h" - -#if (defined ACPI_DEBUGGER || defined ACPI_DISASSEMBLER) - -#define _COMPONENT ACPI_CA_DEBUGGER - ACPI_MODULE_NAME ("dbfileio") - - -/* - * NOTE: this is here for lack of a better place. It is used in all - * flavors of the debugger, need LCD file - */ -#ifdef ACPI_APPLICATION -#include <stdio.h> -FILE *acpi_gbl_debug_file = NULL; -#endif - - -acpi_table_header *acpi_gbl_db_table_ptr = NULL; - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_match_argument - * - * PARAMETERS: User_argument - User command line - * Arguments - Array of commands to match against - * - * RETURN: Index into command array or ACPI_TYPE_NOT_FOUND if not found - * - * DESCRIPTION: Search command array for a command match - * - ******************************************************************************/ - -acpi_object_type -acpi_db_match_argument ( - NATIVE_CHAR *user_argument, - ARGUMENT_INFO *arguments) -{ - u32 i; - - - if (!user_argument || user_argument[0] == 0) { - return (ACPI_TYPE_NOT_FOUND); - } - - for (i = 0; arguments[i].name; i++) { - if (ACPI_STRSTR (arguments[i].name, user_argument) == arguments[i].name) { - return (i); - } - } - - /* Argument not recognized */ - - return (ACPI_TYPE_NOT_FOUND); -} - - -#ifdef ACPI_DEBUGGER -/******************************************************************************* - * - * FUNCTION: Acpi_db_close_debug_file - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: If open, close the current debug output file - * - ******************************************************************************/ - -void -acpi_db_close_debug_file ( - void) -{ - -#ifdef ACPI_APPLICATION - - if (acpi_gbl_debug_file) { - fclose (acpi_gbl_debug_file); - acpi_gbl_debug_file = NULL; - acpi_gbl_db_output_to_file = FALSE; - acpi_os_printf ("Debug output file %s closed\n", acpi_gbl_db_debug_filename); - } -#endif - -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_open_debug_file - * - * PARAMETERS: Name - Filename to open - * - * RETURN: Status - * - * DESCRIPTION: Open a file where debug output will be directed. - * - ******************************************************************************/ - -void -acpi_db_open_debug_file ( - NATIVE_CHAR *name) -{ - -#ifdef ACPI_APPLICATION - - acpi_db_close_debug_file (); - acpi_gbl_debug_file = fopen (name, "w+"); - if (acpi_gbl_debug_file) { - acpi_os_printf ("Debug output file %s opened\n", name); - ACPI_STRCPY (acpi_gbl_db_debug_filename, name); - acpi_gbl_db_output_to_file = TRUE; - } - else { - acpi_os_printf ("Could not open debug file %s\n", name); - } - -#endif -} -#endif - - -#ifdef ACPI_APPLICATION -/******************************************************************************* - * - * FUNCTION: Acpi_db_load_table - * - * PARAMETERS: fp - File that contains table - * Table_ptr - Return value, buffer with table - * Table_lenght - Return value, length of table - * - * RETURN: Status - * - * DESCRIPTION: Load the DSDT from the file pointer - * - ******************************************************************************/ - -static acpi_status -acpi_db_load_table( - FILE *fp, - acpi_table_header **table_ptr, - u32 *table_length) -{ - acpi_table_header table_header; - u8 *aml_start; - u32 aml_length; - u32 actual; - acpi_status status; - - - /* Read the table header */ - - if (fread (&table_header, 1, sizeof (table_header), fp) != sizeof (acpi_table_header)) { - acpi_os_printf ("Couldn't read the table header\n"); - return (AE_BAD_SIGNATURE); - } - - - /* Validate the table header/length */ - - status = acpi_tb_validate_table_header (&table_header); - if ((ACPI_FAILURE (status)) || - (table_header.length > 0x800000)) /* 8 Mbyte should be enough */ { - acpi_os_printf ("Table header is invalid!\n"); - return (AE_ERROR); - } - - - /* We only support a limited number of table types */ - - if (ACPI_STRNCMP ((char *) table_header.signature, DSDT_SIG, 4) && - ACPI_STRNCMP ((char *) table_header.signature, PSDT_SIG, 4) && - ACPI_STRNCMP ((char *) table_header.signature, SSDT_SIG, 4)) { - acpi_os_printf ("Table signature is invalid\n"); - ACPI_DUMP_BUFFER (&table_header, sizeof (acpi_table_header)); - return (AE_ERROR); - } - - /* Allocate a buffer for the table */ - - *table_length = table_header.length; - *table_ptr = acpi_os_allocate ((size_t) *table_length); - if (!*table_ptr) { - acpi_os_printf ("Could not allocate memory for ACPI table %4.4s (size=%X)\n", - table_header.signature, table_header.length); - return (AE_NO_MEMORY); - } - - - aml_start = (u8 *) *table_ptr + sizeof (table_header); - aml_length = *table_length - sizeof (table_header); - - /* Copy the header to the buffer */ - - ACPI_MEMCPY (*table_ptr, &table_header, sizeof (table_header)); - - /* Get the rest of the table */ - - actual = fread (aml_start, 1, (size_t) aml_length, fp); - if (actual == aml_length) { - return (AE_OK); - } - - if (actual > 0) { - acpi_os_printf ("Warning - reading table, asked for %X got %X\n", aml_length, actual); - return (AE_OK); - } - - - acpi_os_printf ("Error - could not read the table file\n"); - acpi_os_free (*table_ptr); - *table_ptr = NULL; - *table_length = 0; - - return (AE_ERROR); -} -#endif - - -/******************************************************************************* - * - * FUNCTION: Ae_local_load_table - * - * PARAMETERS: Table_ptr - pointer to a buffer containing the entire - * table to be loaded - * - * RETURN: Status - * - * DESCRIPTION: This function is called to load a table from the caller's - * buffer. The buffer must contain an entire ACPI Table including - * a valid header. The header fields will be verified, and if it - * is determined that the table is invalid, the call will fail. - * - * If the call fails an appropriate status will be returned. - * - ******************************************************************************/ - -acpi_status -ae_local_load_table ( - acpi_table_header *table_ptr) -{ - acpi_status status; - acpi_table_desc table_info; - - - ACPI_FUNCTION_TRACE ("Ae_local_load_table"); - - if (!table_ptr) { - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - table_info.pointer = table_ptr; - status = acpi_tb_recognize_table (&table_info, ACPI_TABLE_SECONDARY); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - - /* Install the new table into the local data structures */ - - status = acpi_tb_install_table (&table_info); - if (ACPI_FAILURE (status)) { - /* Free table allocated by Acpi_tb_get_table */ - - acpi_tb_delete_single_table (&table_info); - return_ACPI_STATUS (status); - } - - -#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) - status = acpi_ns_load_table (table_info.installed_desc, acpi_gbl_root_node); - if (ACPI_FAILURE (status)) { - /* Uninstall table and free the buffer */ - - acpi_tb_delete_acpi_table (ACPI_TABLE_DSDT); - return_ACPI_STATUS (status); - } -#endif - - return_ACPI_STATUS (status); -} - - -#ifdef ACPI_APPLICATION -acpi_status -acpi_db_get_acpi_table ( - NATIVE_CHAR *filename) -{ - FILE *fp; - u32 table_length; - acpi_status status; - - /* Open the file */ - - fp = fopen (filename, "rb"); - if (!fp) { - acpi_os_printf ("Could not open file %s\n", filename); - return (AE_ERROR); - } - - - /* Get the entire file */ - - fprintf (stderr, "Loading Acpi table from file %s\n", filename); - status = acpi_db_load_table (fp, &acpi_gbl_db_table_ptr, &table_length); - fclose(fp); - - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Couldn't get table from the file\n"); - return (status); - } - - return (AE_OK); - } -#endif - -/******************************************************************************* - * - * FUNCTION: Acpi_db_load_acpi_table - * - * PARAMETERS: Filname - File where table is located - * - * RETURN: Status - * - * DESCRIPTION: Load an ACPI table from a file - * - ******************************************************************************/ - -acpi_status -acpi_db_load_acpi_table ( - NATIVE_CHAR *filename) { -#ifdef ACPI_APPLICATION - acpi_status status; - - - status = acpi_db_get_acpi_table (filename); - if (ACPI_FAILURE (status)) { - return (status); - } - - /* Attempt to recognize and install the table */ - - status = ae_local_load_table (acpi_gbl_db_table_ptr); - if (ACPI_FAILURE (status)) { - if (status == AE_ALREADY_EXISTS) { - acpi_os_printf ("Table %4.4s is already installed\n", - acpi_gbl_db_table_ptr->signature); - } - else { - acpi_os_printf ("Could not install table, %s\n", - acpi_format_exception (status)); - } - - return (status); - } - - fprintf (stderr, "Acpi table [%4.4s] successfully installed and loaded\n", - acpi_gbl_db_table_ptr->signature); - - acpi_gbl_acpi_hardware_present = FALSE; - -#endif /* ACPI_APPLICATION */ - return (AE_OK); -} - - -#endif /* ACPI_DEBUGGER */ - diff --git a/drivers/acpi/debugger/dbhistry.c b/drivers/acpi/debugger/dbhistry.c deleted file mode 100644 index 6a5e6879b5fb..000000000000 --- a/drivers/acpi/debugger/dbhistry.c +++ /dev/null @@ -1,189 +0,0 @@ -/****************************************************************************** - * - * Module Name: dbhistry - debugger HISTORY command - * $Revision: 25 $ - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2002, R. Byron Moore - * - * 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 "acpi.h" -#include "acdebug.h" - -#ifdef ACPI_DEBUGGER - -#define _COMPONENT ACPI_CA_DEBUGGER - ACPI_MODULE_NAME ("dbhistry") - - -#define HI_NO_HISTORY 0 -#define HI_RECORD_HISTORY 1 -#define HISTORY_SIZE 20 - - -typedef struct history_info -{ - NATIVE_CHAR command[80]; - u32 cmd_num; - -} HISTORY_INFO; - - -static HISTORY_INFO acpi_gbl_history_buffer[HISTORY_SIZE]; -static u16 acpi_gbl_lo_history = 0; -static u16 acpi_gbl_num_history = 0; -static u16 acpi_gbl_next_history_index = 0; -static u32 acpi_gbl_next_cmd_num = 1; - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_add_to_history - * - * PARAMETERS: Command_line - Command to add - * - * RETURN: None - * - * DESCRIPTION: Add a command line to the history buffer. - * - ******************************************************************************/ - -void -acpi_db_add_to_history ( - NATIVE_CHAR *command_line) -{ - - /* Put command into the next available slot */ - - ACPI_STRCPY (acpi_gbl_history_buffer[acpi_gbl_next_history_index].command, command_line); - - acpi_gbl_history_buffer[acpi_gbl_next_history_index].cmd_num = acpi_gbl_next_cmd_num; - - /* Adjust indexes */ - - if ((acpi_gbl_num_history == HISTORY_SIZE) && - (acpi_gbl_next_history_index == acpi_gbl_lo_history)) { - acpi_gbl_lo_history++; - if (acpi_gbl_lo_history >= HISTORY_SIZE) { - acpi_gbl_lo_history = 0; - } - } - - acpi_gbl_next_history_index++; - if (acpi_gbl_next_history_index >= HISTORY_SIZE) { - acpi_gbl_next_history_index = 0; - } - - acpi_gbl_next_cmd_num++; - if (acpi_gbl_num_history < HISTORY_SIZE) { - acpi_gbl_num_history++; - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_display_history - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Display the contents of the history buffer - * - ******************************************************************************/ - -void -acpi_db_display_history (void) -{ - NATIVE_UINT i; - u16 history_index; - - - history_index = acpi_gbl_lo_history; - - /* Dump entire history buffer */ - - for (i = 0; i < acpi_gbl_num_history; i++) { - acpi_os_printf ("%ld %s\n", acpi_gbl_history_buffer[history_index].cmd_num, - acpi_gbl_history_buffer[history_index].command); - - history_index++; - if (history_index >= HISTORY_SIZE) { - history_index = 0; - } - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_get_from_history - * - * PARAMETERS: Command_num_arg - String containing the number of the - * command to be retrieved - * - * RETURN: None - * - * DESCRIPTION: Get a command from the history buffer - * - ******************************************************************************/ - -NATIVE_CHAR * -acpi_db_get_from_history ( - NATIVE_CHAR *command_num_arg) -{ - NATIVE_UINT i; - u16 history_index; - u32 cmd_num; - - - if (command_num_arg == NULL) { - cmd_num = acpi_gbl_next_cmd_num - 1; - } - - else { - cmd_num = ACPI_STRTOUL (command_num_arg, NULL, 0); - } - - /* Search history buffer */ - - history_index = acpi_gbl_lo_history; - for (i = 0; i < acpi_gbl_num_history; i++) { - if (acpi_gbl_history_buffer[history_index].cmd_num == cmd_num) { - /* Found the commnad, return it */ - - return (acpi_gbl_history_buffer[history_index].command); - } - - - history_index++; - if (history_index >= HISTORY_SIZE) { - history_index = 0; - } - } - - acpi_os_printf ("Invalid history number: %d\n", history_index); - return (NULL); -} - - -#endif /* ACPI_DEBUGGER */ - diff --git a/drivers/acpi/debugger/dbinput.c b/drivers/acpi/debugger/dbinput.c deleted file mode 100644 index 24eb73621f08..000000000000 --- a/drivers/acpi/debugger/dbinput.c +++ /dev/null @@ -1,892 +0,0 @@ -/******************************************************************************* - * - * Module Name: dbinput - user front-end to the AML debugger - * $Revision: 87 $ - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2002, R. Byron Moore - * - * 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 "acpi.h" -#include "acdebug.h" - - -#ifdef ACPI_DEBUGGER - -#define _COMPONENT ACPI_CA_DEBUGGER - ACPI_MODULE_NAME ("dbinput") - - -/* - * Top-level debugger commands. - * - * This list of commands must match the string table below it - */ -enum acpi_ex_debugger_commands -{ - CMD_NOT_FOUND = 0, - CMD_NULL, - CMD_ALLOCATIONS, - CMD_ARGS, - CMD_ARGUMENTS, - CMD_BREAKPOINT, - CMD_CALL, - CMD_CLOSE, - CMD_DEBUG, - CMD_DUMP, - CMD_ENABLEACPI, - CMD_EVENT, - CMD_EXECUTE, - CMD_EXIT, - CMD_FIND, - CMD_GO, - CMD_HELP, - CMD_HELP2, - CMD_HISTORY, - CMD_HISTORY_EXE, - CMD_HISTORY_LAST, - CMD_INFORMATION, - CMD_INTEGRITY, - CMD_INTO, - CMD_LEVEL, - CMD_LIST, - CMD_LOAD, - CMD_LOCALS, - CMD_LOCKS, - CMD_METHODS, - CMD_NAMESPACE, - CMD_NOTIFY, - CMD_OBJECT, - CMD_OPEN, - CMD_OWNER, - CMD_PREFIX, - CMD_QUIT, - CMD_REFERENCES, - CMD_RESOURCES, - CMD_RESULTS, - CMD_SET, - CMD_STATS, - CMD_STOP, - CMD_TABLES, - CMD_TERMINATE, - CMD_THREADS, - CMD_TREE, - CMD_UNLOAD -}; - -#define CMD_FIRST_VALID 2 - - -static const COMMAND_INFO acpi_gbl_db_commands[] = -{ {"<NOT FOUND>", 0}, - {"<NULL>", 0}, - {"ALLOCATIONS", 0}, - {"ARGS", 0}, - {"ARGUMENTS", 0}, - {"BREAKPOINT", 1}, - {"CALL", 0}, - {"CLOSE", 0}, - {"DEBUG", 1}, - {"DUMP", 1}, - {"ENABLEACPI", 0}, - {"EVENT", 1}, - {"EXECUTE", 1}, - {"EXIT", 0}, - {"FIND", 1}, - {"GO", 0}, - {"HELP", 0}, - {"?", 0}, - {"HISTORY", 0}, - {"!", 1}, - {"!!", 0}, - {"INFORMATION", 0}, - {"INTEGRITY", 0}, - {"INTO", 0}, - {"LEVEL", 0}, - {"LIST", 0}, - {"LOAD", 1}, - {"LOCALS", 0}, - {"LOCKS", 0}, - {"METHODS", 0}, - {"NAMESPACE", 0}, - {"NOTIFY", 2}, - {"OBJECT", 1}, - {"OPEN", 1}, - {"OWNER", 1}, - {"PREFIX", 0}, - {"QUIT", 0}, - {"REFERENCES", 1}, - {"RESOURCES", 1}, - {"RESULTS", 0}, - {"SET", 3}, - {"STATS", 0}, - {"STOP", 0}, - {"TABLES", 0}, - {"TERMINATE", 0}, - {"THREADS", 3}, - {"TREE", 0}, - {"UNLOAD", 1}, - {NULL, 0} -}; - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_display_help - * - * PARAMETERS: Help_type - Subcommand (optional) - * - * RETURN: None - * - * DESCRIPTION: Print a usage message. - * - ******************************************************************************/ - -void -acpi_db_display_help ( - NATIVE_CHAR *help_type) -{ - - - /* No parameter, just give the overview */ - - if (!help_type) - { - acpi_os_printf ("ACPI CA Debugger Commands\n\n"); - acpi_os_printf ("The following classes of commands are available. Help is available for\n"); - acpi_os_printf ("each class by entering \"Help <Class_name>\"\n\n"); - acpi_os_printf (" [GENERAL] General-Purpose Commands\n"); - acpi_os_printf (" [NAMESPACE] Namespace Access Commands\n"); - acpi_os_printf (" [METHOD] Control Method Execution Commands\n"); - acpi_os_printf (" [FILE] File I/O Commands\n"); - return; - - } - - /* - * Parameter is the command class - * - * The idea here is to keep each class of commands smaller than a screenful - */ - switch (help_type[0]) - { - case 'G': - acpi_os_printf ("\nGeneral-Purpose Commands\n\n"); - acpi_os_printf ("Allocations Display list of current memory allocations\n"); - acpi_os_printf ("Dump <Address>|<Namepath>\n"); - acpi_os_printf (" [Byte|Word|Dword|Qword] Display ACPI objects or memory\n"); - acpi_os_printf ("Enable_acpi Enable ACPI (hardware) mode\n"); - acpi_os_printf ("Help This help screen\n"); - acpi_os_printf ("History Display command history buffer\n"); - acpi_os_printf ("Level [<Debug_level>] [console] Get/Set debug level for file or console\n"); - acpi_os_printf ("Locks Current status of internal mutexes\n"); - acpi_os_printf ("Quit or Exit Exit this command\n"); - acpi_os_printf ("Stats [Allocations|Memory|Misc\n"); - acpi_os_printf (" |Objects|Tables] Display namespace and memory statistics\n"); - acpi_os_printf ("Tables Display info about loaded ACPI tables\n"); - acpi_os_printf ("Unload <Table_sig> [Instance] Unload an ACPI table\n"); - acpi_os_printf ("! <Command_number> Execute command from history buffer\n"); - acpi_os_printf ("!! Execute last command again\n"); - return; - - case 'N': - acpi_os_printf ("\nNamespace Access Commands\n\n"); - acpi_os_printf ("Debug <Namepath> [Arguments] Single Step a control method\n"); - acpi_os_printf ("Event <F|G> <Value> Generate Acpi_event (Fixed/GPE)\n"); - acpi_os_printf ("Execute <Namepath> [Arguments] Execute control method\n"); - acpi_os_printf ("Find <Name> (? is wildcard) Find ACPI name(s) with wildcards\n"); - acpi_os_printf ("Method Display list of loaded control methods\n"); - acpi_os_printf ("Namespace [<Addr>|<Path>] [Depth] Display loaded namespace tree/subtree\n"); - acpi_os_printf ("Notify <Name_path> <Value> Send a notification\n"); - acpi_os_printf ("Objects <Object_type> Display all objects of the given type\n"); - acpi_os_printf ("Owner <Owner_id> [Depth] Display loaded namespace by object owner\n"); - acpi_os_printf ("Prefix [<Name_path>] Set or Get current execution prefix\n"); - acpi_os_printf ("References <Addr> Find all references to object at addr\n"); - acpi_os_printf ("Resources xxx Get and display resources\n"); - acpi_os_printf ("Terminate Delete namespace and all internal objects\n"); - acpi_os_printf ("Thread <Threads><Loops><Name_path> Spawn threads to execute method(s)\n"); - return; - - case 'M': - acpi_os_printf ("\nControl Method Execution Commands\n\n"); - acpi_os_printf ("Arguments (or Args) Display method arguments\n"); - acpi_os_printf ("Breakpoint <Aml_offset> Set an AML execution breakpoint\n"); - acpi_os_printf ("Call Run to next control method invocation\n"); - acpi_os_printf ("Go Allow method to run to completion\n"); - acpi_os_printf ("Information Display info about the current method\n"); - acpi_os_printf ("Into Step into (not over) a method call\n"); - acpi_os_printf ("List [# of Aml Opcodes] Display method ASL statements\n"); - acpi_os_printf ("Locals Display method local variables\n"); - acpi_os_printf ("Results Display method result stack\n"); - acpi_os_printf ("Set <A|L> <#> <Value> Set method data (Arguments/Locals)\n"); - acpi_os_printf ("Stop Terminate control method\n"); - acpi_os_printf ("Tree Display control method calling tree\n"); - acpi_os_printf ("<Enter> Single step next AML opcode (over calls)\n"); - return; - - case 'F': - acpi_os_printf ("\nFile I/O Commands\n\n"); - acpi_os_printf ("Close Close debug output file\n"); - acpi_os_printf ("Open <Output Filename> Open a file for debug output\n"); - acpi_os_printf ("Load <Input Filename> Load ACPI table from a file\n"); - return; - - default: - acpi_os_printf ("Unrecognized Command Class: %X\n", help_type); - return; - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_get_next_token - * - * PARAMETERS: String - Command buffer - * Next - Return value, end of next token - * - * RETURN: Pointer to the start of the next token. - * - * DESCRIPTION: Command line parsing. Get the next token on the command line - * - ******************************************************************************/ - -NATIVE_CHAR * -acpi_db_get_next_token ( - NATIVE_CHAR *string, - NATIVE_CHAR **next) -{ - NATIVE_CHAR *start; - - - /* At end of buffer? */ - - if (!string || !(*string)) - { - return (NULL); - } - - /* Get rid of any spaces at the beginning */ - - if (*string == ' ') - { - while (*string && (*string == ' ')) - { - string++; - } - - if (!(*string)) - { - return (NULL); - } - } - - start = string; - - /* Find end of token */ - - while (*string && (*string != ' ')) - { - string++; - } - - if (!(*string)) - { - *next = NULL; - } - else - { - *string = 0; - *next = string + 1; - } - - return (start); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_get_line - * - * PARAMETERS: Input_buffer - Command line buffer - * - * RETURN: None - * - * DESCRIPTION: Get the next command line from the user. Gets entire line - * up to the next newline - * - ******************************************************************************/ - -u32 -acpi_db_get_line ( - NATIVE_CHAR *input_buffer) -{ - u32 i; - u32 count; - NATIVE_CHAR *next; - NATIVE_CHAR *this; - - - ACPI_STRCPY (acpi_gbl_db_parsed_buf, input_buffer); - ACPI_STRUPR (acpi_gbl_db_parsed_buf); - - this = acpi_gbl_db_parsed_buf; - for (i = 0; i < ACPI_DEBUGGER_MAX_ARGS; i++) - { - acpi_gbl_db_args[i] = acpi_db_get_next_token (this, &next); - if (!acpi_gbl_db_args[i]) - { - break; - } - - this = next; - } - - /* Uppercase the actual command */ - - if (acpi_gbl_db_args[0]) - { - ACPI_STRUPR (acpi_gbl_db_args[0]); - } - - count = i; - if (count) - { - count--; /* Number of args only */ - } - - return (count); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_match_command - * - * PARAMETERS: User_command - User command line - * - * RETURN: Index into command array, -1 if not found - * - * DESCRIPTION: Search command array for a command match - * - ******************************************************************************/ - -u32 -acpi_db_match_command ( - NATIVE_CHAR *user_command) -{ - u32 i; - - - if (!user_command || user_command[0] == 0) - { - return (CMD_NULL); - } - - for (i = CMD_FIRST_VALID; acpi_gbl_db_commands[i].name; i++) - { - if (ACPI_STRSTR (acpi_gbl_db_commands[i].name, user_command) == - acpi_gbl_db_commands[i].name) - { - return (i); - } - } - - /* Command not recognized */ - - return (CMD_NOT_FOUND); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_command_dispatch - * - * PARAMETERS: Input_buffer - Command line buffer - * Walk_state - Current walk - * Op - Current (executing) parse op - * - * RETURN: Status - * - * DESCRIPTION: Command dispatcher. Called from two places: - * - ******************************************************************************/ - -acpi_status -acpi_db_command_dispatch ( - NATIVE_CHAR *input_buffer, - acpi_walk_state *walk_state, - acpi_parse_object *op) -{ - u32 temp; - u32 command_index; - u32 param_count; - NATIVE_CHAR *command_line; - acpi_status status = AE_CTRL_TRUE; - - - /* If Acpi_terminate has been called, terminate this thread */ - - if (acpi_gbl_db_terminate_threads) - { - return (AE_CTRL_TERMINATE); - } - - param_count = acpi_db_get_line (input_buffer); - command_index = acpi_db_match_command (acpi_gbl_db_args[0]); - temp = 0; - - /* Verify that we have the minimum number of params */ - - if (param_count < acpi_gbl_db_commands[command_index].min_args) - { - acpi_os_printf ("%d parameters entered, [%s] requires %d parameters\n", - param_count, acpi_gbl_db_commands[command_index].name, acpi_gbl_db_commands[command_index].min_args); - return (AE_CTRL_TRUE); - } - - /* Decode and dispatch the command */ - - switch (command_index) - { - case CMD_NULL: - if (op) - { - return (AE_OK); - } - break; - - case CMD_ALLOCATIONS: - -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - acpi_ut_dump_allocations ((u32) -1, NULL); -#endif - break; - - case CMD_ARGS: - case CMD_ARGUMENTS: - acpi_db_display_arguments (); - break; - - case CMD_BREAKPOINT: - acpi_db_set_method_breakpoint (acpi_gbl_db_args[1], walk_state, op); - break; - - case CMD_CALL: - acpi_db_set_method_call_breakpoint (op); - status = AE_OK; - break; - - case CMD_CLOSE: - acpi_db_close_debug_file (); - break; - - case CMD_DEBUG: - acpi_db_execute (acpi_gbl_db_args[1], &acpi_gbl_db_args[2], EX_SINGLE_STEP); - break; - - case CMD_DUMP: - acpi_db_decode_and_display_object (acpi_gbl_db_args[1], acpi_gbl_db_args[2]); - break; - - case CMD_ENABLEACPI: - status = acpi_enable(); - if (ACPI_FAILURE(status)) - { - acpi_os_printf("Acpi_enable failed (Status=%X)\n", status); - return (status); - } - break; - - case CMD_EVENT: - acpi_os_printf ("Event command not implemented\n"); - break; - - case CMD_EXECUTE: - acpi_db_execute (acpi_gbl_db_args[1], &acpi_gbl_db_args[2], EX_NO_SINGLE_STEP); - break; - - case CMD_FIND: - status = acpi_db_find_name_in_namespace (acpi_gbl_db_args[1]); - break; - - case CMD_GO: - acpi_gbl_cm_single_step = FALSE; - return (AE_OK); - - case CMD_HELP: - case CMD_HELP2: - acpi_db_display_help (acpi_gbl_db_args[1]); - break; - - case CMD_HISTORY: - acpi_db_display_history (); - break; - - case CMD_HISTORY_EXE: - command_line = acpi_db_get_from_history (acpi_gbl_db_args[1]); - if (!command_line) - { - return (AE_CTRL_TRUE); - } - - status = acpi_db_command_dispatch (command_line, walk_state, op); - if (ACPI_SUCCESS (status)) - { - status = AE_CTRL_TRUE; - } - return (status); - - case CMD_HISTORY_LAST: - command_line = acpi_db_get_from_history (NULL); - if (!command_line) - { - return (AE_CTRL_TRUE); - } - - status = acpi_db_command_dispatch (command_line, walk_state, op); - if (ACPI_SUCCESS (status)) - { - status = AE_CTRL_TRUE; - } - return (status); - - case CMD_INFORMATION: - acpi_db_display_method_info (op); - break; - - case CMD_INTEGRITY: - acpi_db_check_integrity (); - break; - - case CMD_INTO: - if (op) - { - acpi_gbl_cm_single_step = TRUE; - return (AE_OK); - } - break; - - case CMD_LEVEL: - if (param_count == 0) - { - acpi_os_printf ("Current debug level for file output is: %8.8lX\n", acpi_gbl_db_debug_level); - acpi_os_printf ("Current debug level for console output is: %8.8lX\n", acpi_gbl_db_console_debug_level); - } - else if (param_count == 2) - { - temp = acpi_gbl_db_console_debug_level; - acpi_gbl_db_console_debug_level = ACPI_STRTOUL (acpi_gbl_db_args[1], NULL, 16); - acpi_os_printf ("Debug Level for console output was %8.8lX, now %8.8lX\n", temp, acpi_gbl_db_console_debug_level); - } - else - { - temp = acpi_gbl_db_debug_level; - acpi_gbl_db_debug_level = ACPI_STRTOUL (acpi_gbl_db_args[1], NULL, 16); - acpi_os_printf ("Debug Level for file output was %8.8lX, now %8.8lX\n", temp, acpi_gbl_db_debug_level); - } - break; - - case CMD_LIST: - acpi_db_disassemble_aml (acpi_gbl_db_args[1], op); - break; - - case CMD_LOAD: - status = acpi_db_load_acpi_table (acpi_gbl_db_args[1]); - if (ACPI_FAILURE (status)) - { - return (status); - } - break; - - case CMD_LOCKS: - acpi_db_display_locks (); - break; - - case CMD_LOCALS: - acpi_db_display_locals (); - break; - - case CMD_METHODS: - status = acpi_db_display_objects ("METHOD", acpi_gbl_db_args[1]); - break; - - case CMD_NAMESPACE: - acpi_db_dump_namespace (acpi_gbl_db_args[1], acpi_gbl_db_args[2]); - break; - - case CMD_NOTIFY: - temp = ACPI_STRTOUL (acpi_gbl_db_args[2], NULL, 0); - acpi_db_send_notify (acpi_gbl_db_args[1], temp); - break; - - case CMD_OBJECT: - ACPI_STRUPR (acpi_gbl_db_args[1]); - status = acpi_db_display_objects (acpi_gbl_db_args[1], acpi_gbl_db_args[2]); - break; - - case CMD_OPEN: - acpi_db_open_debug_file (acpi_gbl_db_args[1]); - break; - - case CMD_OWNER: - acpi_db_dump_namespace_by_owner (acpi_gbl_db_args[1], acpi_gbl_db_args[2]); - break; - - case CMD_PREFIX: - acpi_db_set_scope (acpi_gbl_db_args[1]); - break; - - case CMD_REFERENCES: - acpi_db_find_references (acpi_gbl_db_args[1]); - break; - - case CMD_RESOURCES: - acpi_db_display_resources (acpi_gbl_db_args[1]); - break; - - case CMD_RESULTS: - acpi_db_display_results (); - break; - - case CMD_SET: - acpi_db_set_method_data (acpi_gbl_db_args[1], acpi_gbl_db_args[2], acpi_gbl_db_args[3]); - break; - - case CMD_STATS: - status = acpi_db_display_statistics (acpi_gbl_db_args[1]); - break; - - case CMD_STOP: - return (AE_NOT_IMPLEMENTED); - - case CMD_TABLES: - acpi_db_display_table_info (acpi_gbl_db_args[1]); - break; - - case CMD_TERMINATE: - acpi_db_set_output_destination (ACPI_DB_REDIRECTABLE_OUTPUT); - acpi_ut_subsystem_shutdown (); - - /* TBD: [Restructure] Need some way to re-initialize without re-creating the semaphores! */ - - /* Acpi_initialize (NULL); */ - break; - - case CMD_THREADS: - acpi_db_create_execution_threads (acpi_gbl_db_args[1], acpi_gbl_db_args[2], acpi_gbl_db_args[3]); - break; - - case CMD_TREE: - acpi_db_display_calling_tree (); - break; - - case CMD_UNLOAD: - acpi_db_unload_acpi_table (acpi_gbl_db_args[1], acpi_gbl_db_args[2]); - break; - - case CMD_EXIT: - case CMD_QUIT: - if (op) - { - acpi_os_printf ("Method execution terminated\n"); - return (AE_CTRL_TERMINATE); - } - - if (!acpi_gbl_db_output_to_file) - { - acpi_dbg_level = DEBUG_DEFAULT; - } - - /* Shutdown */ - - /* Acpi_ut_subsystem_shutdown (); */ - acpi_db_close_debug_file (); - - acpi_gbl_db_terminate_threads = TRUE; - - return (AE_CTRL_TERMINATE); - - case CMD_NOT_FOUND: - default: - acpi_os_printf ("Unknown Command\n"); - return (AE_CTRL_TRUE); - } - - - /* Add all commands that come here to the history buffer */ - - acpi_db_add_to_history (input_buffer); - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_execute_thread - * - * PARAMETERS: Context - Not used - * - * RETURN: None - * - * DESCRIPTION: Debugger execute thread. Waits for a command line, then - * simply dispatches it. - * - ******************************************************************************/ - -void ACPI_SYSTEM_XFACE -acpi_db_execute_thread ( - void *context) -{ - acpi_status status = AE_OK; - acpi_status Mstatus; - - - while (status != AE_CTRL_TERMINATE) - { - acpi_gbl_method_executing = FALSE; - acpi_gbl_step_to_next_call = FALSE; - - Mstatus = acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_READY); - if (ACPI_FAILURE (Mstatus)) - { - return; - } - - status = acpi_db_command_dispatch (acpi_gbl_db_line_buf, NULL, NULL); - - Mstatus = acpi_ut_release_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); - if (ACPI_FAILURE (Mstatus)) - { - return; - } - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_single_thread - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Debugger execute thread. Waits for a command line, then - * simply dispatches it. - * - ******************************************************************************/ - -void -acpi_db_single_thread ( - void) -{ - - acpi_gbl_method_executing = FALSE; - acpi_gbl_step_to_next_call = FALSE; - - (void) acpi_db_command_dispatch (acpi_gbl_db_line_buf, NULL, NULL); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_user_commands - * - * PARAMETERS: Prompt - User prompt (depends on mode) - * Op - Current executing parse op - * - * RETURN: None - * - * DESCRIPTION: Command line execution for the AML debugger. Commands are - * matched and dispatched here. - * - ******************************************************************************/ - -acpi_status -acpi_db_user_commands ( - NATIVE_CHAR prompt, - acpi_parse_object *op) -{ - acpi_status status = AE_OK; - - - /* TBD: [Restructure] Need a separate command line buffer for step mode */ - - while (!acpi_gbl_db_terminate_threads) - { - /* Force output to console until a command is entered */ - - acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); - - /* Different prompt if method is executing */ - - if (!acpi_gbl_method_executing) - { - acpi_os_printf ("%1c ", ACPI_DEBUGGER_COMMAND_PROMPT); - } - else - { - acpi_os_printf ("%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT); - } - - /* Get the user input line */ - - (void) acpi_os_get_line (acpi_gbl_db_line_buf); - - /* Check for single or multithreaded debug */ - - if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) - { - /* - * Signal the debug thread that we have a command to execute, - * and wait for the command to complete. - */ - status = acpi_ut_release_mutex (ACPI_MTX_DEBUG_CMD_READY); - if (ACPI_FAILURE (status)) - { - return (status); - } - - status = acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); - if (ACPI_FAILURE (status)) - { - return (status); - } - } - else - { - /* Just call to the command line interpreter */ - - acpi_db_single_thread (); - } - } - - /* - * Only this thread (the original thread) should actually terminate the subsystem, - * because all the semaphores are deleted during termination - */ - status = acpi_terminate (); - return (status); -} - - -#endif /* ACPI_DEBUGGER */ - diff --git a/drivers/acpi/debugger/dbstats.c b/drivers/acpi/debugger/dbstats.c deleted file mode 100644 index 32ba47dd4c86..000000000000 --- a/drivers/acpi/debugger/dbstats.c +++ /dev/null @@ -1,459 +0,0 @@ -/******************************************************************************* - * - * Module Name: dbstats - Generation and display of ACPI table statistics - * $Revision: 61 $ - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2002, R. Byron Moore - * - * 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 <acpi.h> -#include <acdebug.h> -#include <acnamesp.h> - -#ifdef ACPI_DEBUGGER - -#define _COMPONENT ACPI_CA_DEBUGGER - ACPI_MODULE_NAME ("dbstats") - -/* - * Statistics subcommands - */ -static ARGUMENT_INFO acpi_db_stat_types [] = -{ {"ALLOCATIONS"}, - {"OBJECTS"}, - {"MEMORY"}, - {"MISC"}, - {"TABLES"}, - {"SIZES"}, - {"STACK"}, - {NULL} /* Must be null terminated */ -}; - -#define CMD_STAT_ALLOCATIONS 0 -#define CMD_STAT_OBJECTS 1 -#define CMD_STAT_MEMORY 2 -#define CMD_STAT_MISC 3 -#define CMD_STAT_TABLES 4 -#define CMD_STAT_SIZES 5 -#define CMD_STAT_STACK 6 - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_enumerate_object - * - * PARAMETERS: Obj_desc - Object to be counted - * - * RETURN: None - * - * DESCRIPTION: Add this object to the global counts, by object type. - * Limited recursion handles subobjects and packages, and this - * is probably acceptable within the AML debugger only. - * - ******************************************************************************/ - -void -acpi_db_enumerate_object ( - acpi_operand_object *obj_desc) -{ - u32 i; - - - if (!obj_desc) - { - return; - } - - - /* Enumerate this object first */ - - acpi_gbl_num_objects++; - - if (ACPI_GET_OBJECT_TYPE (obj_desc) > INTERNAL_TYPE_NODE_MAX) - { - acpi_gbl_obj_type_count_misc++; - } - else - { - acpi_gbl_obj_type_count [ACPI_GET_OBJECT_TYPE (obj_desc)]++; - } - - /* Count the sub-objects */ - - switch (ACPI_GET_OBJECT_TYPE (obj_desc)) - { - case ACPI_TYPE_PACKAGE: - for (i = 0; i < obj_desc->package.count; i++) - { - acpi_db_enumerate_object (obj_desc->package.elements[i]); - } - break; - - case ACPI_TYPE_DEVICE: - acpi_db_enumerate_object (obj_desc->device.sys_handler); - acpi_db_enumerate_object (obj_desc->device.drv_handler); - acpi_db_enumerate_object (obj_desc->device.addr_handler); - break; - - case ACPI_TYPE_BUFFER_FIELD: - if (acpi_ns_get_secondary_object (obj_desc)) - { - acpi_gbl_obj_type_count [ACPI_TYPE_BUFFER_FIELD]++; - } - break; - - case ACPI_TYPE_REGION: - acpi_gbl_obj_type_count [INTERNAL_TYPE_REGION_FIELD ]++; - acpi_db_enumerate_object (obj_desc->region.addr_handler); - break; - - case ACPI_TYPE_POWER: - acpi_db_enumerate_object (obj_desc->power_resource.sys_handler); - acpi_db_enumerate_object (obj_desc->power_resource.drv_handler); - break; - - case ACPI_TYPE_PROCESSOR: - acpi_db_enumerate_object (obj_desc->processor.sys_handler); - acpi_db_enumerate_object (obj_desc->processor.drv_handler); - acpi_db_enumerate_object (obj_desc->processor.addr_handler); - break; - - case ACPI_TYPE_THERMAL: - acpi_db_enumerate_object (obj_desc->thermal_zone.sys_handler); - acpi_db_enumerate_object (obj_desc->thermal_zone.drv_handler); - acpi_db_enumerate_object (obj_desc->thermal_zone.addr_handler); - break; - - default: - break; - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_classify_one_object - * - * PARAMETERS: Callback for Walk_namespace - * - * RETURN: Status - * - * DESCRIPTION: Enumerate both the object descriptor (including subobjects) and - * the parent namespace node. - * - ******************************************************************************/ - -acpi_status -acpi_db_classify_one_object ( - acpi_handle obj_handle, - u32 nesting_level, - void *context, - void **return_value) -{ - acpi_namespace_node *node; - acpi_operand_object *obj_desc; - u32 type; - - - acpi_gbl_num_nodes++; - - node = (acpi_namespace_node *) obj_handle; - obj_desc = acpi_ns_get_attached_object (node); - - acpi_db_enumerate_object (obj_desc); - - type = node->type; - if (type > INTERNAL_TYPE_NODE_MAX) - { - acpi_gbl_node_type_count_misc++; - } - - else - { - acpi_gbl_node_type_count [type]++; - } - - return AE_OK; - - - /* TBD: These need to be counted during the initial parsing phase */ - /* - if (Acpi_ps_is_named_op (Op->Opcode)) - { - Num_nodes++; - } - - if (Is_method) - { - Num_method_elements++; - } - - Num_grammar_elements++; - Op = Acpi_ps_get_depth_next (Root, Op); - - Size_of_parse_tree = (Num_grammar_elements - Num_method_elements) * (u32) sizeof (acpi_parse_object); - Size_of_method_trees = Num_method_elements * (u32) sizeof (acpi_parse_object); - Size_of_node_entries = Num_nodes * (u32) sizeof (acpi_namespace_node); - Size_of_acpi_objects = Num_nodes * (u32) sizeof (acpi_operand_object); - - */ -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_count_namespace_objects - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Count and classify the entire namespace, including all - * namespace nodes and attached objects. - * - ******************************************************************************/ - -void -acpi_db_count_namespace_objects ( - void) -{ - u32 i; - - - acpi_gbl_num_nodes = 0; - acpi_gbl_num_objects = 0; - - acpi_gbl_obj_type_count_misc = 0; - for (i = 0; i < (INTERNAL_TYPE_NODE_MAX -1); i++) - { - acpi_gbl_obj_type_count [i] = 0; - acpi_gbl_node_type_count [i] = 0; - } - - (void) acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - FALSE, acpi_db_classify_one_object, NULL, NULL); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_display_statistics - * - * PARAMETERS: Type_arg - Subcommand - * - * RETURN: Status - * - * DESCRIPTION: Display various statistics - * - ******************************************************************************/ - -acpi_status -acpi_db_display_statistics ( - NATIVE_CHAR *type_arg) -{ - u32 i; - u32 type; - u32 size; -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - u32 outstanding; -#endif - - - if (!acpi_gbl_DSDT) - { - acpi_os_printf ("*** Warning: There is no DSDT loaded\n"); - } - - if (!type_arg) - { - acpi_os_printf ("The following subcommands are available:\n ALLOCATIONS, OBJECTS, MEMORY, MISC, SIZES, TABLES\n"); - return (AE_OK); - } - - ACPI_STRUPR (type_arg); - type = acpi_db_match_argument (type_arg, acpi_db_stat_types); - if (type == (u32) -1) - { - acpi_os_printf ("Invalid or unsupported argument\n"); - return (AE_OK); - } - - - switch (type) - { - case CMD_STAT_ALLOCATIONS: -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - acpi_ut_dump_allocation_info (); -#endif - break; - - case CMD_STAT_TABLES: - - acpi_os_printf ("ACPI Table Information:\n\n"); - if (acpi_gbl_DSDT) - { - acpi_os_printf ("DSDT Length:................% 7ld (%X)\n", acpi_gbl_DSDT->length, acpi_gbl_DSDT->length); - } - break; - - case CMD_STAT_OBJECTS: - - acpi_db_count_namespace_objects (); - - acpi_os_printf ("\nObjects defined in the current namespace:\n\n"); - - acpi_os_printf ("%16.16s % 10.10s % 10.10s\n", "ACPI_TYPE", "NODES", "OBJECTS"); - - for (i = 0; i < INTERNAL_TYPE_NODE_MAX; i++) - { - acpi_os_printf ("%16.16s % 10ld% 10ld\n", acpi_ut_get_type_name (i), - acpi_gbl_node_type_count [i], acpi_gbl_obj_type_count [i]); - } - acpi_os_printf ("%16.16s % 10ld% 10ld\n", "Misc/Unknown", - acpi_gbl_node_type_count_misc, acpi_gbl_obj_type_count_misc); - - acpi_os_printf ("%16.16s % 10ld% 10ld\n", "TOTALS:", - acpi_gbl_num_nodes, acpi_gbl_num_objects); - break; - - case CMD_STAT_MEMORY: - -#ifdef ACPI_DBG_TRACK_ALLOCATIONS - acpi_os_printf ("\n----Object and Cache Statistics---------------------------------------------\n"); - - for (i = 0; i < ACPI_NUM_MEM_LISTS; i++) - { - acpi_os_printf ("\n%s\n", acpi_gbl_memory_lists[i].list_name); - - if (acpi_gbl_memory_lists[i].max_cache_depth > 0) - { - acpi_os_printf (" Cache: [Depth Max Avail Size] % 7d % 7d % 7d % 7d B\n", - acpi_gbl_memory_lists[i].cache_depth, - acpi_gbl_memory_lists[i].max_cache_depth, - acpi_gbl_memory_lists[i].max_cache_depth - acpi_gbl_memory_lists[i].cache_depth, - (acpi_gbl_memory_lists[i].cache_depth * acpi_gbl_memory_lists[i].object_size)); - - acpi_os_printf (" Cache: [Requests Hits Misses Obj_size] % 7d % 7d % 7d % 7d B\n", - acpi_gbl_memory_lists[i].cache_requests, - acpi_gbl_memory_lists[i].cache_hits, - acpi_gbl_memory_lists[i].cache_requests - acpi_gbl_memory_lists[i].cache_hits, - acpi_gbl_memory_lists[i].object_size); - } - - outstanding = acpi_gbl_memory_lists[i].total_allocated - - acpi_gbl_memory_lists[i].total_freed - - acpi_gbl_memory_lists[i].cache_depth; - - if (acpi_gbl_memory_lists[i].object_size) - { - size = ACPI_ROUND_UP_TO_1K (outstanding * acpi_gbl_memory_lists[i].object_size); - } - else - { - size = ACPI_ROUND_UP_TO_1K (acpi_gbl_memory_lists[i].current_total_size); - } - - acpi_os_printf (" Mem: [Alloc Free Outstanding Size] % 7d % 7d % 7d % 7d Kb\n", - acpi_gbl_memory_lists[i].total_allocated, - acpi_gbl_memory_lists[i].total_freed, - outstanding, size); - } -#endif - - break; - - case CMD_STAT_MISC: - - acpi_os_printf ("\nMiscellaneous Statistics:\n\n"); - acpi_os_printf ("Calls to Acpi_ps_find:.. ........% 7ld\n", acpi_gbl_ps_find_count); - acpi_os_printf ("Calls to Acpi_ns_lookup:..........% 7ld\n", acpi_gbl_ns_lookup_count); - - acpi_os_printf ("\n"); - - acpi_os_printf ("Mutex usage:\n\n"); - for (i = 0; i < NUM_MTX; i++) - { - acpi_os_printf ("%-28s: % 7ld\n", acpi_ut_get_mutex_name (i), acpi_gbl_acpi_mutex_info[i].use_count); - } - break; - - - case CMD_STAT_SIZES: - - acpi_os_printf ("\nInternal object sizes:\n\n"); - - acpi_os_printf ("Common %3d\n", sizeof (ACPI_OBJECT_COMMON)); - acpi_os_printf ("Number %3d\n", sizeof (ACPI_OBJECT_INTEGER)); - acpi_os_printf ("String %3d\n", sizeof (ACPI_OBJECT_STRING)); - acpi_os_printf ("Buffer %3d\n", sizeof (ACPI_OBJECT_BUFFER)); - acpi_os_printf ("Package %3d\n", sizeof (ACPI_OBJECT_PACKAGE)); - acpi_os_printf ("Buffer_field %3d\n", sizeof (ACPI_OBJECT_BUFFER_FIELD)); - acpi_os_printf ("Device %3d\n", sizeof (ACPI_OBJECT_DEVICE)); - acpi_os_printf ("Event %3d\n", sizeof (ACPI_OBJECT_EVENT)); - acpi_os_printf ("Method %3d\n", sizeof (ACPI_OBJECT_METHOD)); - acpi_os_printf ("Mutex %3d\n", sizeof (ACPI_OBJECT_MUTEX)); - acpi_os_printf ("Region %3d\n", sizeof (ACPI_OBJECT_REGION)); - acpi_os_printf ("Power_resource %3d\n", sizeof (ACPI_OBJECT_POWER_RESOURCE)); - acpi_os_printf ("Processor %3d\n", sizeof (ACPI_OBJECT_PROCESSOR)); - acpi_os_printf ("Thermal_zone %3d\n", sizeof (ACPI_OBJECT_THERMAL_ZONE)); - acpi_os_printf ("Region_field %3d\n", sizeof (ACPI_OBJECT_REGION_FIELD)); - acpi_os_printf ("Bank_field %3d\n", sizeof (ACPI_OBJECT_BANK_FIELD)); - acpi_os_printf ("Index_field %3d\n", sizeof (ACPI_OBJECT_INDEX_FIELD)); - acpi_os_printf ("Reference %3d\n", sizeof (ACPI_OBJECT_REFERENCE)); - acpi_os_printf ("Notify_handler %3d\n", sizeof (ACPI_OBJECT_NOTIFY_HANDLER)); - acpi_os_printf ("Addr_handler %3d\n", sizeof (ACPI_OBJECT_ADDR_HANDLER)); - acpi_os_printf ("Extra %3d\n", sizeof (ACPI_OBJECT_EXTRA)); - acpi_os_printf ("Data %3d\n", sizeof (ACPI_OBJECT_DATA)); - - acpi_os_printf ("\n"); - - acpi_os_printf ("Parse_object %3d\n", sizeof (ACPI_PARSE_OBJ_COMMON)); - acpi_os_printf ("Parse_object_named %3d\n", sizeof (ACPI_PARSE_OBJ_NAMED)); - acpi_os_printf ("Parse_object_asl %3d\n", sizeof (ACPI_PARSE_OBJ_ASL)); - acpi_os_printf ("Operand_object %3d\n", sizeof (acpi_operand_object)); - acpi_os_printf ("Namespace_node %3d\n", sizeof (acpi_namespace_node)); - - break; - - - case CMD_STAT_STACK: -#if defined(ACPI_DEBUG_OUTPUT) - - size = (u32) (acpi_gbl_entry_stack_pointer - acpi_gbl_lowest_stack_pointer); - - acpi_os_printf ("\nSubsystem Stack Usage:\n\n"); - acpi_os_printf ("Entry Stack Pointer %X\n", acpi_gbl_entry_stack_pointer); - acpi_os_printf ("Lowest Stack Pointer %X\n", acpi_gbl_lowest_stack_pointer); - acpi_os_printf ("Stack Use %X (%d)\n", size, size); - acpi_os_printf ("Deepest Procedure Nesting %d\n", acpi_gbl_deepest_nesting); -#endif - break; - - default: - break; - } - - acpi_os_printf ("\n"); - return (AE_OK); -} - - -#endif /* ACPI_DEBUGGER */ diff --git a/drivers/acpi/debugger/dbutils.c b/drivers/acpi/debugger/dbutils.c deleted file mode 100644 index 72539e36eaa1..000000000000 --- a/drivers/acpi/debugger/dbutils.c +++ /dev/null @@ -1,380 +0,0 @@ -/******************************************************************************* - * - * Module Name: dbutils - AML debugger utilities - * $Revision: 56 $ - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2002, R. Byron Moore - * - * 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 "acpi.h" -#include "acparser.h" -#include "amlcode.h" -#include "acnamesp.h" -#include "acdebug.h" -#include "acdispat.h" - - -#ifdef ACPI_DEBUGGER - -#define _COMPONENT ACPI_CA_DEBUGGER - ACPI_MODULE_NAME ("dbutils") - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_set_output_destination - * - * PARAMETERS: Output_flags - Current flags word - * - * RETURN: None - * - * DESCRIPTION: Set the current destination for debugger output. Alos sets - * the debug output level accordingly. - * - ******************************************************************************/ - -void -acpi_db_set_output_destination ( - u32 output_flags) -{ - - acpi_gbl_db_output_flags = (u8) output_flags; - - if ((output_flags & ACPI_DB_REDIRECTABLE_OUTPUT) && acpi_gbl_db_output_to_file) { - acpi_dbg_level = acpi_gbl_db_debug_level; - } - else { - acpi_dbg_level = acpi_gbl_db_console_debug_level; - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_dump_buffer - * - * PARAMETERS: Address - Pointer to the buffer - * - * RETURN: None - * - * DESCRIPTION: Print a portion of a buffer - * - ******************************************************************************/ - -void -acpi_db_dump_buffer ( - u32 address) -{ - - acpi_os_printf ("\nLocation %X:\n", address); - - acpi_dbg_level |= ACPI_LV_TABLES; - acpi_ut_dump_buffer (ACPI_TO_POINTER (address), 64, DB_BYTE_DISPLAY, ACPI_UINT32_MAX); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_dump_object - * - * PARAMETERS: Obj_desc - External ACPI object to dump - * Level - Nesting level. - * - * RETURN: None - * - * DESCRIPTION: Dump the contents of an ACPI external object - * - ******************************************************************************/ - -void -acpi_db_dump_object ( - acpi_object *obj_desc, - u32 level) -{ - u32 i; - - - if (!obj_desc) { - acpi_os_printf ("[Null Object]\n"); - return; - } - - for (i = 0; i < level; i++) { - acpi_os_printf (" "); - } - - switch (obj_desc->type) { - case ACPI_TYPE_ANY: - - acpi_os_printf ("[Object Reference] = %p\n", obj_desc->reference.handle); - break; - - - case ACPI_TYPE_INTEGER: - - acpi_os_printf ("[Integer] = %8.8X%8.8X\n", - ACPI_HIDWORD (obj_desc->integer.value), - ACPI_LODWORD (obj_desc->integer.value)); - break; - - - case ACPI_TYPE_STRING: - - acpi_os_printf ("[String] Value: "); - for (i = 0; i < obj_desc->string.length; i++) { - acpi_os_printf ("%c", obj_desc->string.pointer[i]); - } - acpi_os_printf ("\n"); - break; - - - case ACPI_TYPE_BUFFER: - - acpi_os_printf ("[Buffer] Length %.2X = ", obj_desc->buffer.length); - acpi_ut_dump_buffer ((u8 *) obj_desc->buffer.pointer, obj_desc->buffer.length, DB_DWORD_DISPLAY, _COMPONENT); - break; - - - case ACPI_TYPE_PACKAGE: - - acpi_os_printf ("[Package] Contains %d Elements: \n", obj_desc->package.count); - - for (i = 0; i < obj_desc->package.count; i++) { - acpi_db_dump_object (&obj_desc->package.elements[i], level+1); - } - break; - - - case INTERNAL_TYPE_REFERENCE: - - acpi_os_printf ("[Object Reference] = %p\n", obj_desc->reference.handle); - break; - - - case ACPI_TYPE_PROCESSOR: - - acpi_os_printf ("[Processor]\n"); - break; - - - case ACPI_TYPE_POWER: - - acpi_os_printf ("[Power Resource]\n"); - break; - - - default: - - acpi_os_printf ("[Unknown Type] %X \n", obj_desc->type); - break; - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_prep_namestring - * - * PARAMETERS: Name - String to prepare - * - * RETURN: None - * - * DESCRIPTION: Translate all forward slashes and dots to backslashes. - * - ******************************************************************************/ - -void -acpi_db_prep_namestring ( - NATIVE_CHAR *name) -{ - - - if (!name) { - return; - } - - ACPI_STRUPR (name); - - /* Convert a leading forward slash to a backslash */ - - if (*name == '/') { - *name = '\\'; - } - - /* Ignore a leading backslash, this is the root prefix */ - - if (*name == '\\') { - name++; - } - - /* Convert all slash path separators to dots */ - - while (*name) { - if ((*name == '/') || - (*name == '\\')) { - *name = '.'; - } - - name++; - } -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_second_pass_parse - * - * PARAMETERS: Root - Root of the parse tree - * - * RETURN: Status - * - * DESCRIPTION: Second pass parse of the ACPI tables. We need to wait until - * second pass to parse the control methods - * - ******************************************************************************/ - -acpi_status -acpi_db_second_pass_parse ( - acpi_parse_object *root) -{ - acpi_parse_object *op = root; - acpi_parse_object *method; - acpi_parse_object *search_op; - acpi_parse_object *start_op; - acpi_status status = AE_OK; - u32 base_aml_offset; - acpi_walk_state *walk_state; - - - ACPI_FUNCTION_ENTRY (); - - - acpi_os_printf ("Pass two parse ....\n"); - - while (op) { - if (op->common.aml_opcode == AML_METHOD_OP) { - method = op; - - /* Create a new walk state for the parse */ - - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, - NULL, NULL, NULL); - if (!walk_state) { - return (AE_NO_MEMORY); - } - - /* Init the Walk State */ - - walk_state->parser_state.aml = - walk_state->parser_state.aml_start = method->named.data; - walk_state->parser_state.aml_end = - walk_state->parser_state.pkg_end = method->named.data + method->named.length; - walk_state->parser_state.start_scope = op; - - walk_state->descending_callback = acpi_ds_load1_begin_op; - walk_state->ascending_callback = acpi_ds_load1_end_op; - - /* Perform the AML parse */ - - status = acpi_ps_parse_aml (walk_state); - - base_aml_offset = (method->common.value.arg)->common.aml_offset + 1; - start_op = (method->common.value.arg)->common.next; - search_op = start_op; - - while (search_op) { - search_op->common.aml_offset += base_aml_offset; - search_op = acpi_ps_get_depth_next (start_op, search_op); - } - } - - if (op->common.aml_opcode == AML_REGION_OP) { - /* TBD: [Investigate] this isn't quite the right thing to do! */ - /* - * - * Method = (ACPI_DEFERRED_OP *) Op; - * Status = Acpi_ps_parse_aml (Op, Method->Body, Method->Body_length); - */ - } - - if (ACPI_FAILURE (status)) { - break; - } - - op = acpi_ps_get_depth_next (root, op); - } - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_local_ns_lookup - * - * PARAMETERS: Name - Name to lookup - * - * RETURN: Pointer to a namespace node - * - * DESCRIPTION: Lookup a name in the ACPI namespace - * - * Note: Currently begins search from the root. Could be enhanced to use - * the current prefix (scope) node as the search beginning point. - * - ******************************************************************************/ - -acpi_namespace_node * -acpi_db_local_ns_lookup ( - NATIVE_CHAR *name) -{ - NATIVE_CHAR *internal_path; - acpi_status status; - acpi_namespace_node *node = NULL; - - - acpi_db_prep_namestring (name); - - /* Build an internal namestring */ - - status = acpi_ns_internalize_name (name, &internal_path); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Invalid namestring: %s\n", name); - return (NULL); - } - - /* - * Lookup the name. - * (Uses root node as the search starting point) - */ - status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, - ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE, NULL, &node); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Could not locate name: %s %s\n", name, acpi_format_exception (status)); - } - - ACPI_MEM_FREE (internal_path); - return (node); -} - - -#endif /* ACPI_DEBUGGER */ - - diff --git a/drivers/acpi/debugger/dbxface.c b/drivers/acpi/debugger/dbxface.c deleted file mode 100644 index c2945fa1eaf8..000000000000 --- a/drivers/acpi/debugger/dbxface.c +++ /dev/null @@ -1,388 +0,0 @@ -/******************************************************************************* - * - * Module Name: dbxface - AML Debugger external interfaces - * $Revision: 64 $ - * - ******************************************************************************/ - -/* - * Copyright (C) 2000 - 2002, R. Byron Moore - * - * 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 "acpi.h" -#include "amlcode.h" -#include "acdebug.h" -#include "acdisasm.h" - - -#ifdef ACPI_DEBUGGER - -#define _COMPONENT ACPI_CA_DEBUGGER - ACPI_MODULE_NAME ("dbxface") - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_single_step - * - * PARAMETERS: Walk_state - Current walk - * Op - Current executing op - * Opcode_class - Class of the current AML Opcode - * - * RETURN: Status - * - * DESCRIPTION: Called just before execution of an AML opcode. - * - ******************************************************************************/ - -acpi_status -acpi_db_single_step ( - acpi_walk_state *walk_state, - acpi_parse_object *op, - u32 opcode_class) -{ - acpi_parse_object *next; - acpi_status status = AE_OK; - u32 original_debug_level; - acpi_parse_object *display_op; - acpi_parse_object *parent_op; - - - ACPI_FUNCTION_ENTRY (); - - /* Check for single-step breakpoint */ - - if (walk_state->method_breakpoint && - (walk_state->method_breakpoint <= op->common.aml_offset)) { - /* Check if the breakpoint has been reached or passed */ - /* Hit the breakpoint, resume single step, reset breakpoint */ - - acpi_os_printf ("***Break*** at AML offset %X\n", op->common.aml_offset); - acpi_gbl_cm_single_step = TRUE; - acpi_gbl_step_to_next_call = FALSE; - walk_state->method_breakpoint = 0; - } - - /* Check for user breakpoint (Must be on exact Aml offset) */ - - else if (walk_state->user_breakpoint && - (walk_state->user_breakpoint == op->common.aml_offset)) { - acpi_os_printf ("***User_breakpoint*** at AML offset %X\n", op->common.aml_offset); - acpi_gbl_cm_single_step = TRUE; - acpi_gbl_step_to_next_call = FALSE; - walk_state->method_breakpoint = 0; - } - - - /* - * Check if this is an opcode that we are interested in -- - * namely, opcodes that have arguments - */ - if (op->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { - return (AE_OK); - } - - switch (opcode_class) { - case AML_CLASS_UNKNOWN: - case AML_CLASS_ARGUMENT: /* constants, literals, etc. do nothing */ - return (AE_OK); - - default: - /* All other opcodes -- continue */ - break; - } - - /* - * Under certain debug conditions, display this opcode and its operands - */ - if ((acpi_gbl_db_output_to_file) || - (acpi_gbl_cm_single_step) || - (acpi_dbg_level & ACPI_LV_PARSE)) { - if ((acpi_gbl_db_output_to_file) || - (acpi_dbg_level & ACPI_LV_PARSE)) { - acpi_os_printf ("\n[Aml_debug] Next AML Opcode to execute:\n"); - } - - /* - * Display this op (and only this op - zero out the NEXT field temporarily, - * and disable parser trace output for the duration of the display because - * we don't want the extraneous debug output) - */ - original_debug_level = acpi_dbg_level; - acpi_dbg_level &= ~(ACPI_LV_PARSE | ACPI_LV_FUNCTIONS); - next = op->common.next; - op->common.next = NULL; - - - display_op = op; - parent_op = op->common.parent; - if (parent_op) { - if ((walk_state->control_state) && - (walk_state->control_state->common.state == ACPI_CONTROL_PREDICATE_EXECUTING)) { - /* - * We are executing the predicate of an IF or WHILE statement - * Search upwards for the containing IF or WHILE so that the - * entire predicate can be displayed. - */ - while (parent_op) { - if ((parent_op->common.aml_opcode == AML_IF_OP) || - (parent_op->common.aml_opcode == AML_WHILE_OP)) { - display_op = parent_op; - break; - } - parent_op = parent_op->common.parent; - } - } - else { - while (parent_op) { - if ((parent_op->common.aml_opcode == AML_IF_OP) || - (parent_op->common.aml_opcode == AML_ELSE_OP) || - (parent_op->common.aml_opcode == AML_SCOPE_OP) || - (parent_op->common.aml_opcode == AML_METHOD_OP) || - (parent_op->common.aml_opcode == AML_WHILE_OP)) { - break; - } - display_op = parent_op; - parent_op = parent_op->common.parent; - } - } - } - - /* Now we can display it */ - - acpi_dm_disassemble (walk_state, display_op, ACPI_UINT32_MAX); - - if ((op->common.aml_opcode == AML_IF_OP) || - (op->common.aml_opcode == AML_WHILE_OP)) { - if (walk_state->control_state->common.value) { - acpi_os_printf ("Predicate = [True], IF block was executed\n"); - } - else { - acpi_os_printf ("Predicate = [False], Skipping IF block\n"); - } - } - - else if (op->common.aml_opcode == AML_ELSE_OP) { - acpi_os_printf ("Predicate = [False], ELSE block was executed\n"); - } - - /* Restore everything */ - - op->common.next = next; - acpi_os_printf ("\n\n"); - acpi_dbg_level = original_debug_level; - } - - /* If we are not single stepping, just continue executing the method */ - - if (!acpi_gbl_cm_single_step) { - return (AE_OK); - } - - /* - * If we are executing a step-to-call command, - * Check if this is a method call. - */ - if (acpi_gbl_step_to_next_call) { - if (op->common.aml_opcode != AML_INT_METHODCALL_OP) { - /* Not a method call, just keep executing */ - - return (AE_OK); - } - - /* Found a method call, stop executing */ - - acpi_gbl_step_to_next_call = FALSE; - } - - /* - * If the next opcode is a method call, we will "step over" it - * by default. - */ - if (op->common.aml_opcode == AML_INT_METHODCALL_OP) { - acpi_gbl_cm_single_step = FALSE; /* No more single step while executing called method */ - - /* Set the breakpoint on/before the call, it will stop execution as soon as we return */ - - walk_state->method_breakpoint = 1; /* Must be non-zero! */ - } - - - /* TBD: [Investigate] what are the namespace locking issues here */ - - /* Acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); */ - - /* Go into the command loop and await next user command */ - - acpi_gbl_method_executing = TRUE; - status = AE_CTRL_TRUE; - while (status == AE_CTRL_TRUE) { - if (acpi_gbl_debugger_configuration == DEBUGGER_MULTI_THREADED) { - /* Handshake with the front-end that gets user command lines */ - - status = acpi_ut_release_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); - if (ACPI_FAILURE (status)) { - return (status); - } - status = acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_READY); - if (ACPI_FAILURE (status)) { - return (status); - } - } - - else { - /* Single threaded, we must get a command line ourselves */ - - /* Force output to console until a command is entered */ - - acpi_db_set_output_destination (ACPI_DB_CONSOLE_OUTPUT); - - /* Different prompt if method is executing */ - - if (!acpi_gbl_method_executing) { - acpi_os_printf ("%1c ", ACPI_DEBUGGER_COMMAND_PROMPT); - } - else { - acpi_os_printf ("%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT); - } - - /* Get the user input line */ - - (void) acpi_os_get_line (acpi_gbl_db_line_buf); - } - - status = acpi_db_command_dispatch (acpi_gbl_db_line_buf, walk_state, op); - } - - /* Acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); */ - - /* User commands complete, continue execution of the interrupted method */ - - return (status); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_initialize - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Init and start debugger - * - ******************************************************************************/ - -acpi_status -acpi_db_initialize (void) -{ - acpi_status status; - - - /* Init globals */ - - acpi_gbl_db_buffer = NULL; - acpi_gbl_db_filename = NULL; - acpi_gbl_db_output_to_file = FALSE; - - acpi_gbl_db_debug_level = ACPI_LV_VERBOSITY2; - acpi_gbl_db_console_debug_level = NORMAL_DEFAULT | ACPI_LV_TABLES; - acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; - - acpi_gbl_db_opt_tables = FALSE; - acpi_gbl_db_opt_disasm = FALSE; - acpi_gbl_db_opt_stats = FALSE; - acpi_gbl_db_opt_verbose = TRUE; - acpi_gbl_db_opt_ini_methods = TRUE; - - acpi_gbl_db_buffer = acpi_os_allocate (ACPI_DEBUG_BUFFER_SIZE); - if (!acpi_gbl_db_buffer) { - return (AE_NO_MEMORY); - } - ACPI_MEMSET (acpi_gbl_db_buffer, 0, ACPI_DEBUG_BUFFER_SIZE); - - /* Initial scope is the root */ - - acpi_gbl_db_scope_buf [0] = '\\'; - acpi_gbl_db_scope_buf [1] = 0; - acpi_gbl_db_scope_node = acpi_gbl_root_node; - - /* - * If configured for multi-thread support, the debug executor runs in - * a separate thread so that the front end can be in another address - * space, environment, or even another machine. - */ - if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) { - /* These were created with one unit, grab it */ - - status = acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_COMPLETE); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Could not get debugger mutex\n"); - return (status); - } - status = acpi_ut_acquire_mutex (ACPI_MTX_DEBUG_CMD_READY); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Could not get debugger mutex\n"); - return (status); - } - - /* Create the debug execution thread to execute commands */ - - status = acpi_os_queue_for_execution (0, acpi_db_execute_thread, NULL); - if (ACPI_FAILURE (status)) { - acpi_os_printf ("Could not start debugger thread\n"); - return (status); - } - } - - if (!acpi_gbl_db_opt_verbose) { - acpi_gbl_db_opt_disasm = TRUE; - acpi_gbl_db_opt_stats = FALSE; - } - - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: Acpi_db_terminate - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Stop debugger - * - ******************************************************************************/ - -void -acpi_db_terminate (void) -{ - - if (acpi_gbl_db_table_ptr) { - acpi_os_free (acpi_gbl_db_table_ptr); - } - if (acpi_gbl_db_buffer) { - acpi_os_free (acpi_gbl_db_buffer); - } -} - - -#endif /* ACPI_DEBUGGER */ diff --git a/drivers/acpi/include/acpiosxf.h b/drivers/acpi/include/acpiosxf.h index b6cac89b91b9..d6df38a20ed2 100644 --- a/drivers/acpi/include/acpiosxf.h +++ b/drivers/acpi/include/acpiosxf.h @@ -261,10 +261,6 @@ acpi_os_writable ( void *pointer, u32 length); -u32 -acpi_os_get_timer ( - void); - acpi_status acpi_os_signal ( u32 function, @@ -284,10 +280,6 @@ acpi_os_vprintf ( const NATIVE_CHAR *format, va_list args); -void -acpi_os_redirect_output ( - void *destination); - /* * Debug input @@ -298,16 +290,4 @@ acpi_os_get_line ( NATIVE_CHAR *buffer); -/* - * Debug - */ - -void -acpi_os_dbg_assert( - void *failed_assertion, - void *file_name, - u32 line_number, - NATIVE_CHAR *message); - - #endif /* __ACPIOSXF_H__ */ diff --git a/drivers/acpi/kdb/README.txt b/drivers/acpi/kdb/README.txt deleted file mode 100644 index 700c6b237386..000000000000 --- a/drivers/acpi/kdb/README.txt +++ /dev/null @@ -1,36 +0,0 @@ -Using the ACPI debugger with kdb --------------------------------- - -ACPI CA includes a full-featured debugger, which allows the examination of -a running system's ACPI tables, as well as running and stepping through -control methods. - -Configuration -------------- -1) Edit the main acpi Makefile. On the ACPI_CFLAGS line, remove the '#', thus - enabling the debugger. - -2) Download the latest kdb patch from: - - ftp://oss.sgi.com/www/projects/kdb/download/ix86/ - - Follow the instructions at http://oss.sgi.com/projects/kdb/ on how to - install the patch and configure KDB. - -3) This would probably be a good time to recompile the kernel, and make sure - kdb works (Hitting the Pause key should drop you into it. Type "go" to exit - it. - -4) The kdb <--> ACPI debugger interface is a module. Type "make modules", and - it will be built and placed in drivers/acpi/kdb. - -5) Change to that directory and type "insmod kdbm_acpi.o". This loads the - module we just built. - -6) Break back into kdb. If you type help, you should now see "acpi" listed as - a command, at the bottom. - -7) Type "acpi". You are now in the ACPI debugger. While hosted by kdb, it is - wholly separate, and has many ACPI-specific commands. Type "?" or "help" - to get a listing of the command categories, and then "help <category>" for - a list of commands and their descriptions diff --git a/drivers/acpi/kdb/kdbm_acpi.c b/drivers/acpi/kdb/kdbm_acpi.c deleted file mode 100644 index e14ea39b9546..000000000000 --- a/drivers/acpi/kdb/kdbm_acpi.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * kdbm_acpi.c - kdb debugger module interface for ACPI debugger - * - * Copyright (C) 2000 Andrew Grover - * - * 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/types.h> -#include <linux/kdb.h> -#include <linux/module.h> - -#include "acpi.h" -#include "acdebug.h" - -extern int acpi_in_debugger; - -static int -kdbm_acpi(int argc, const char **argv, const char **envp, struct pt_regs *regs) -{ - acpi_in_debugger = 1; - - acpi_db_user_commands(DB_COMMAND_PROMPT, NULL); - - acpi_in_debugger = 0; - - return 0; -} - -int -init_module(void) -{ - kdb_register("acpi", kdbm_acpi, "", "Enter ACPI debugger", 0); - - return 0; -} - -void -cleanup_module(void) -{ - kdb_unregister("acpi"); -} diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 62e85d568255..6e663fa8694b 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -134,16 +134,6 @@ acpi_os_allocate(ACPI_SIZE size) return kmalloc(size, GFP_KERNEL); } -void * -acpi_os_callocate(ACPI_SIZE size) -{ - void *ptr = acpi_os_allocate(size); - if (ptr) - memset(ptr, 0, size); - - return ptr; -} - void acpi_os_free(void *ptr) { @@ -523,37 +513,6 @@ acpi_os_read_pci_configuration ( #endif /*CONFIG_ACPI_PCI*/ -acpi_status -acpi_os_load_module ( - char *module_name) -{ - ACPI_FUNCTION_TRACE ("os_load_module"); - - if (!module_name) - return_ACPI_STATUS (AE_BAD_PARAMETER); - - if (request_module(module_name) < 0) { - ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Unable to load module [%s].\n", module_name)); - return_ACPI_STATUS (AE_ERROR); - } - - return_ACPI_STATUS (AE_OK); -} - -acpi_status -acpi_os_unload_module ( - char *module_name) -{ - if (!module_name) - return AE_BAD_PARAMETER; - - /* TODO: How on Linux? */ - /* this is done automatically for all modules with - use_count = 0, I think. see: MOD_INC_USE_COUNT -ASG */ - - return AE_OK; -} - /* * See acpi_os_queue_for_execution() @@ -695,9 +654,10 @@ acpi_os_create_semaphore( ACPI_FUNCTION_TRACE ("os_create_semaphore"); - sem = acpi_os_callocate(sizeof(struct semaphore)); + sem = acpi_os_allocate(sizeof(struct semaphore)); if (!sem) return_ACPI_STATUS (AE_NO_MEMORY); + memset(sem, 0, sizeof(struct semaphore)); sema_init(sem, initial_units); @@ -913,12 +873,3 @@ acpi_os_signal ( return AE_OK; } - -acpi_status -acpi_os_breakpoint(NATIVE_CHAR *msg) -{ - acpi_os_printf("breakpoint: %s", msg); - - return AE_OK; -} - diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 5d5edb42f24c..847b5938ce79 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -288,7 +288,7 @@ acpi_pci_irq_derive ( while (!irq && (bridge = bridge->bus->self)) { pin = (pin + PCI_SLOT(bridge->devfn)) % 4; irq = acpi_pci_irq_lookup(0, bridge->bus->number, PCI_SLOT(bridge->devfn), pin); - }; + } if (!irq) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to derive IRQ for device %s\n", dev->slot_name)); diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index b94b85b1cea4..4389f1d64bb8 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -54,12 +54,12 @@ static int acpi_pci_link_add (struct acpi_device *device); static int acpi_pci_link_remove (struct acpi_device *device, int type); static struct acpi_driver acpi_pci_link_driver = { - .name = ACPI_PCI_LINK_DRIVER_NAME, - .class = ACPI_PCI_LINK_CLASS, - .ids = ACPI_PCI_LINK_HID, - .ops = { - .add = acpi_pci_link_add, - .remove = acpi_pci_link_remove, + .name = ACPI_PCI_LINK_DRIVER_NAME, + .class = ACPI_PCI_LINK_CLASS, + .ids = ACPI_PCI_LINK_HID, + .ops = { + .add = acpi_pci_link_add, + .remove = acpi_pci_link_remove, }, }; diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index a56fedea61b4..57f235dbd102 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -51,8 +51,8 @@ static struct acpi_driver acpi_pci_root_driver = { .class = ACPI_PCI_ROOT_CLASS, .ids = ACPI_PCI_ROOT_HID, .ops = { - .add = acpi_pci_root_add, - .remove = acpi_pci_root_remove, + .add = acpi_pci_root_add, + .remove = acpi_pci_root_remove, }, }; diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 68f71d76df6b..c62fa049ced3 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -23,8 +23,6 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -#define ACPI_C - #include <linux/config.h> #include <linux/kernel.h> #include <linux/module.h> diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index 48f3b32dbfa9..4c7590389282 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c @@ -26,15 +26,15 @@ * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse * engineering the Windows drivers * Yasushi Nagato - changes for linux kernel 2.4 -> 2.5 + * Rob Miller - TV out and hotkeys help * * * TODO - * provide version info in proc - * add Fn key status * */ -#define TOSHIBA_ACPI_VERSION "0.12" +#define TOSHIBA_ACPI_VERSION "0.13" +#define PROC_INTERFACE_VERSION 1 #include <linux/kernel.h> #include <linux/module.h> @@ -43,9 +43,10 @@ #include <linux/proc_fs.h> #include <linux/version.h> -#define KERNEL24 (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)) +#include <acconfig.h> +#define OLD_ACPI_INTERFACE (ACPI_CA_VERSION < 0x20020000) -#if KERNEL24 +#if OLD_ACPI_INTERFACE #include <acpi.h> extern struct proc_dir_entry* bm_proc_root; #define acpi_root_dir bm_proc_root @@ -82,10 +83,13 @@ MODULE_LICENSE("GPL"); #define HCI_SUCCESS 0x0000 #define HCI_FAILURE 0x1000 #define HCI_NOT_SUPPORTED 0x8000 +#define HCI_EMPTY 0x8c00 /* registers */ #define HCI_FAN 0x0004 +#define HCI_SYSTEM_EVENT 0x0016 #define HCI_VIDEO_OUT 0x001c +#define HCI_HOTKEY_EVENT 0x001e #define HCI_LCD_BRIGHTNESS 0x002a /* field definitions */ @@ -94,6 +98,7 @@ MODULE_LICENSE("GPL"); #define HCI_LCD_BRIGHTNESS_LEVELS (1 << HCI_LCD_BRIGHTNESS_BITS) #define HCI_VIDEO_OUT_LCD 0x1 #define HCI_VIDEO_OUT_CRT 0x2 +#define HCI_VIDEO_OUT_TV 0x4 /* utility */ @@ -104,6 +109,23 @@ _set_bit(u32* word, u32 mask, int value) *word = (*word & ~mask) | (mask * value); } +/* an sscanf that takes explicit string length */ +static int +snscanf(const char* str, int n, const char* format, ...) +{ + va_list args; + int result; + char* str2 = kmalloc(n + 1, GFP_KERNEL); + if (str2 == 0) return 0; + strncpy(str2, str, n); + str2[n] = 0; + va_start(args, format); + result = vsscanf(str2, format, args); + va_end(args); + kfree(str2); + return result; +} + /* This is the common code at the end of every proc read handler. I don't * understand it yet. */ @@ -226,14 +248,15 @@ hci_read1(u32 reg, u32* out1, u32* result) #define PROC_LCD "lcd" #define PROC_VIDEO "video" #define PROC_FAN "fan" +#define PROC_KEYS "keys" +#define PROC_VERSION "version" static struct proc_dir_entry* toshiba_proc_dir = NULL; static int force_fan; +static int last_key_event; +static int key_event_valid; /* proc file handlers - * - * WARNING: The write handlers are using sscanf on non-zero-terminated - * buffers. This may result in memory reads past the buffer bounds. */ static int @@ -270,7 +293,7 @@ proc_write_lcd(struct file* file, const char* buffer, unsigned long count, u32 hci_result; /* ISSUE: %i doesn't work with hex values as advertised */ - if (sscanf(buffer, " brightness : %i", &value) == 1 && + if (snscanf(buffer, count, " brightness : %i", &value) == 1 && value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) { value = value << HCI_LCD_BRIGHTNESS_SHIFT; hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result); @@ -297,8 +320,10 @@ proc_read_video(char* page, char** start, off_t off, int count, int* eof, if (hci_result == HCI_SUCCESS) { int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0; int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0; + int is_tv = (value & HCI_VIDEO_OUT_TV ) ? 1 : 0; p += sprintf(p, "lcd_out: %d\n", is_lcd); p += sprintf(p, "crt_out: %d\n", is_crt); + p += sprintf(p, "tv_out: %d\n", is_tv); } else { p += sprintf(p, "ERROR\n"); goto end; @@ -316,15 +341,18 @@ proc_write_video(struct file* file, const char* buffer, unsigned long count, const char* buffer_end = buffer + count; int lcd_out = -1; int crt_out = -1; + int tv_out = -1; u32 hci_result; int video_out; /* scan expression. Multiple expressions may be delimited with ; */ do { - if (sscanf(buffer, " lcd_out : %i", &value) == 1) + if (snscanf(buffer, count, " lcd_out : %i", &value) == 1) lcd_out = value & 1; - else if (sscanf(buffer, " crt_out : %i", &value) == 1) + else if (snscanf(buffer, count, " crt_out : %i", &value) == 1) crt_out = value & 1; + else if (snscanf(buffer, count, " tv_out : %i", &value) == 1) + tv_out = value & 1; /* advance to one character past the next ; */ do ++buffer; while ((buffer < buffer_end) && (*(buffer-1) != ';')); @@ -337,6 +365,8 @@ proc_write_video(struct file* file, const char* buffer, unsigned long count, _set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out); if (crt_out != -1) _set_bit(&new_video_out, HCI_VIDEO_OUT_CRT, crt_out); + if (tv_out != -1) + _set_bit(&new_video_out, HCI_VIDEO_OUT_TV, tv_out); /* To avoid unnecessary video disruption, only write the new * video setting if something changed. */ if (new_video_out != video_out) @@ -376,7 +406,7 @@ proc_write_fan(struct file* file, const char* buffer, unsigned long count, int value; u32 hci_result; - if (sscanf(buffer, " force_on : %i", &value) == 1 && + if (snscanf(buffer, count, " force_on : %i", &value) == 1 && value >= 0 && value <= 1) { hci_write1(HCI_FAN, value, &hci_result); if (hci_result != HCI_SUCCESS) @@ -390,6 +420,68 @@ proc_write_fan(struct file* file, const char* buffer, unsigned long count, return count; } +static int +proc_read_keys(char* page, char** start, off_t off, int count, int* eof, + void* context) +{ + char* p = page; + u32 hci_result; + u32 value; + + if (off != 0) goto end; + + if (!key_event_valid) { + hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result); + if (hci_result == HCI_SUCCESS) { + key_event_valid = 1; + last_key_event = value; + } else if (hci_result == HCI_EMPTY) { + /* better luck next time */ + } else { + p += sprintf(p, "ERROR\n"); + goto end; + } + } + + p += sprintf(p, "hotkey_ready: %d\n", key_event_valid); + p += sprintf(p, "hotkey: 0x%04x\n", last_key_event); + +end: + return end_proc_read(p, page, off, count, start, eof); +} + +static int +proc_write_keys(struct file* file, const char* buffer, unsigned long count, + void* data) +{ + int value; + + if (snscanf(buffer, count, " hotkey_ready : %i", &value) == 1 && + value == 0) { + key_event_valid = 0; + } else { + return -EINVAL; + } + + return count; +} + +static int +proc_read_version(char* page, char** start, off_t off, int count, int* eof, + void* context) +{ + char* p = page; + + if (off != 0) goto end; + + p += sprintf(p, "driver: %s\n", TOSHIBA_ACPI_VERSION); + p += sprintf(p, "proc_interface: %d\n", + PROC_INTERFACE_VERSION); + +end: + return end_proc_read(p, page, off, count, start, eof); +} + /* proc and module init */ @@ -410,6 +502,13 @@ add_device(void) toshiba_proc_dir, proc_read_fan, 0); if (proc) proc->write_proc = proc_write_fan; + proc = create_proc_read_entry(PROC_KEYS, S_IFREG | S_IRUGO | S_IWUSR, + toshiba_proc_dir, proc_read_keys, 0); + if (proc) proc->write_proc = proc_write_keys; + + proc = create_proc_read_entry(PROC_VERSION, S_IFREG | S_IRUGO | S_IWUSR, + toshiba_proc_dir, proc_read_version, 0); + return(AE_OK); } @@ -419,6 +518,8 @@ remove_device(void) remove_proc_entry(PROC_LCD, toshiba_proc_dir); remove_proc_entry(PROC_VIDEO, toshiba_proc_dir); remove_proc_entry(PROC_FAN, toshiba_proc_dir); + remove_proc_entry(PROC_KEYS, toshiba_proc_dir); + remove_proc_entry(PROC_VERSION, toshiba_proc_dir); return(AE_OK); } @@ -437,6 +538,10 @@ toshiba_acpi_init(void) printk("Toshiba Laptop ACPI Extras version %s\n", TOSHIBA_ACPI_VERSION); force_fan = 0; + key_event_valid = 0; + + /* enable event fifo */ + hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result); toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir); if (!toshiba_proc_dir) { diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 6101e17ebe13..b3e37b7e66b2 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -266,8 +266,8 @@ #include <linux/proc_fs.h> #include <linux/blkpg.h> #include <linux/init.h> +#include <linux/fcntl.h> -#include <asm/fcntl.h> #include <asm/uaccess.h> /* used to tell the module to turn on full debugging messages */ diff --git a/drivers/hotplug/cpqphp.h b/drivers/hotplug/cpqphp.h index 618bf2c739d2..18f99fad6989 100644 --- a/drivers/hotplug/cpqphp.h +++ b/drivers/hotplug/cpqphp.h @@ -292,16 +292,14 @@ struct controller { struct pci_resource *io_head; struct pci_resource *bus_head; struct pci_dev *pci_dev; - struct pci_ops *pci_ops; + struct pci_bus *pci_bus; struct proc_dir_entry* proc_entry; struct proc_dir_entry* proc_entry2; struct event_info event_queue[10]; struct slot *slot; u8 next_event; u8 interrupt; - u8 bus; - u8 device; - u8 function; + u8 bus; /* bus number for the pci hotplug controller */ u8 rev; u8 slot_device_offset; u8 first_slot; @@ -695,7 +693,8 @@ static inline int cpq_get_latch_status (struct controller *ctrl, struct slot *sl return 1; hp_slot = slot->device - ctrl->slot_device_offset; - dbg(__FUNCTION__": slot->device = %d, ctrl->slot_device_offset = %d \n", slot->device, ctrl->slot_device_offset); + dbg("%s: slot->device = %d, ctrl->slot_device_offset = %d \n", + __FUNCTION__, slot->device, ctrl->slot_device_offset); status = (readl(ctrl->hpc_reg + INT_INPUT_CLEAR) & (0x01L << hp_slot)); @@ -733,7 +732,7 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl) DECLARE_WAITQUEUE(wait, current); int retval = 0; - dbg(__FUNCTION__" - start\n"); + dbg("%s - start\n", __FUNCTION__); add_wait_queue(&ctrl->queue, &wait); set_current_state(TASK_INTERRUPTIBLE); /* Sleep for up to 1 second to wait for the LED to change. */ @@ -743,7 +742,7 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl) if (signal_pending(current)) retval = -EINTR; - dbg(__FUNCTION__" - end\n"); + dbg("%s - end\n", __FUNCTION__); return retval; } diff --git a/drivers/hotplug/cpqphp_core.c b/drivers/hotplug/cpqphp_core.c index f7b5a5b6930c..aec0ecc145bc 100644 --- a/drivers/hotplug/cpqphp_core.c +++ b/drivers/hotplug/cpqphp_core.c @@ -314,7 +314,7 @@ static int ctrl_slot_setup (struct controller * ctrl, void *smbios_start, void * void *slot_entry= NULL; int result; - dbg(__FUNCTION__"\n"); + dbg("%s\n", __FUNCTION__); tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); @@ -467,7 +467,7 @@ static int ctrl_slot_cleanup (struct controller * ctrl) // // Output: SUCCESS or FAILURE //============================================================================= -static int get_slot_mapping (struct pci_ops *ops, u8 bus_num, u8 dev_num, u8 *slot) +static int get_slot_mapping (struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot) { struct irq_routing_table *PCIIRQRoutingInfoLength; u32 work; @@ -476,7 +476,7 @@ static int get_slot_mapping (struct pci_ops *ops, u8 bus_num, u8 dev_num, u8 *sl u8 tbus, tdevice, tslot, bridgeSlot; - dbg(__FUNCTION__" %p, %d, %d, %p\n", ops, bus_num, dev_num, slot); + dbg("%s: %p, %d, %d, %p\n", __FUNCTION__, bus, bus_num, dev_num, slot); bridgeSlot = 0xFF; @@ -490,7 +490,6 @@ static int get_slot_mapping (struct pci_ops *ops, u8 bus_num, u8 dev_num, u8 *sl return -1; } - for (loop = 0; loop < len; ++loop) { tbus = PCIIRQRoutingInfoLength->slots[loop].bus; tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn >> 3; @@ -499,7 +498,8 @@ static int get_slot_mapping (struct pci_ops *ops, u8 bus_num, u8 dev_num, u8 *sl if ((tbus == bus_num) && (tdevice == dev_num)) { *slot = tslot; - if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength ); + if (PCIIRQRoutingInfoLength != NULL) + kfree(PCIIRQRoutingInfoLength); return 0; } else { // Didn't get a match on the target PCI device. Check if the @@ -508,10 +508,11 @@ static int get_slot_mapping (struct pci_ops *ops, u8 bus_num, u8 dev_num, u8 *sl // device, I need to save the bridge's slot number. If I can't // find an entry for the target device, I will have to assume it's // on the other side of the bridge, and assign it the bridge's slot. - pci_read_config_dword_nodev (ops, tbus, tdevice, 0, PCI_REVISION_ID, &work); + bus->number = tbus; + pci_bus_read_config_dword (bus, PCI_DEVFN(tdevice, 0), PCI_REVISION_ID, &work); if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) { - pci_read_config_dword_nodev (ops, tbus, tdevice, 0, PCI_PRIMARY_BUS, &work); + pci_bus_read_config_dword (bus, PCI_DEVFN(tdevice, 0), PCI_PRIMARY_BUS, &work); // See if bridge's secondary bus matches target bus. if (((work >> 8) & 0x000000FF) == (long) bus_num) { bridgeSlot = tslot; @@ -521,7 +522,6 @@ static int get_slot_mapping (struct pci_ops *ops, u8 bus_num, u8 dev_num, u8 *sl } - // If we got here, we didn't find an entry in the IRQ mapping table // for the target PCI device. If we did determine that the target // device is on the other side of a PCI-to-PCI bridge, return the @@ -592,7 +592,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) if (slot == NULL) return -ENODEV; - dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); ctrl = slot->ctrl; if (ctrl == NULL) @@ -627,7 +627,7 @@ static int process_SI (struct hotplug_slot *hotplug_slot) if (slot == NULL) return -ENODEV; - dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); ctrl = slot->ctrl; if (ctrl == NULL) @@ -667,7 +667,7 @@ static int process_SS (struct hotplug_slot *hotplug_slot) if (slot == NULL) return -ENODEV; - dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); ctrl = slot->ctrl; if (ctrl == NULL) @@ -695,7 +695,7 @@ static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value) struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); struct controller *ctrl; - dbg(__FUNCTION__"\n"); + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); if (slot == NULL) return -ENODEV; @@ -716,7 +716,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) if (slot == NULL) return -ENODEV; - dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); ctrl = slot->ctrl; if (ctrl == NULL) @@ -734,7 +734,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) if (slot == NULL) return -ENODEV; - dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); ctrl = slot->ctrl; if (ctrl == NULL) @@ -752,7 +752,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) if (slot == NULL) return -ENODEV; - dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name); + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); ctrl = slot->ctrl; if (ctrl == NULL) @@ -770,8 +770,8 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) if (slot == NULL) return -ENODEV; - - dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name); + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); ctrl = slot->ctrl; if (ctrl == NULL) @@ -820,7 +820,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) // TODO: This code can be made to support non-Compaq or Intel subsystem IDs rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid); if (rc) { - err(__FUNCTION__" : pci_read_config_word failed\n"); + err("%s : pci_read_config_word failed\n", __FUNCTION__); return rc; } dbg("Subsystem Vendor ID: %x\n", subsystem_vid); @@ -831,14 +831,14 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); if (!ctrl) { - err(__FUNCTION__" : out of memory\n"); + err("%s : out of memory\n", __FUNCTION__); return -ENOMEM; } memset(ctrl, 0, sizeof(struct controller)); rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid); if (rc) { - err(__FUNCTION__" : pci_read_config_word failed\n"); + err("%s : pci_read_config_word failed\n", __FUNCTION__); goto err_free_ctrl; } @@ -991,12 +991,20 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dbg (" pcix_support %s\n", ctrl->pcix_support == 0 ? "not supported" : "supported"); ctrl->pci_dev = pdev; - ctrl->pci_ops = pdev->bus->ops; + + /* make our own copy of the pci bus structure, as we like tweaking it a lot */ + ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL); + if (!ctrl->pci_bus) { + err("out of memory\n"); + rc = -ENOMEM; + goto err_free_ctrl; + } + memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); + ctrl->bus = pdev->bus->number; - ctrl->device = PCI_SLOT(pdev->devfn); - ctrl->function = PCI_FUNC(pdev->devfn); ctrl->rev = rev; - dbg("bus device function rev: %d %d %d %d\n", ctrl->bus, ctrl->device, ctrl->function, ctrl->rev); + dbg("bus device function rev: %d %d %d %d\n", ctrl->bus, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev); init_MUTEX(&ctrl->crit_sect); init_waitqueue_head(&ctrl->queue); @@ -1004,7 +1012,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* initialize our threads if they haven't already been started up */ rc = one_time_init(); if (rc) { - goto err_free_ctrl; + goto err_free_bus; } dbg("pdev = %p\n", pdev); @@ -1015,7 +1023,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_resource_len(pdev, 0), MY_NAME)) { err("cannot reserve MMIO region\n"); rc = -ENOMEM; - goto err_free_ctrl; + goto err_free_bus; } ctrl->hpc_reg = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); @@ -1043,7 +1051,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) // in this case it will always be called for the "base" // bus/dev/func of a slot. // CS: this is leveraging the PCIIRQ routing code from the kernel (pci-pc.c: get_irq_routing_table) - rc = get_slot_mapping(ctrl->pci_ops, pdev->bus->number, (readb(ctrl->hpc_reg + SLOT_MASK) >> 4), &(ctrl->first_slot)); + rc = get_slot_mapping(ctrl->pci_bus, pdev->bus->number, (readb(ctrl->hpc_reg + SLOT_MASK) >> 4), &(ctrl->first_slot)); dbg("get_slot_mapping: first_slot = %d, returned = %d\n", ctrl->first_slot, rc); if (rc) { err(msg_initialization_err, rc); @@ -1053,7 +1061,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) // Store PCI Config Space for all devices on this bus rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK)); if (rc) { - err(__FUNCTION__": unable to save PCI configuration data, error %d\n", rc); + err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc); goto err_iounmap; } @@ -1080,7 +1088,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rc = ctrl_slot_setup(ctrl, smbios_start, smbios_table); if (rc) { err(msg_initialization_err, 6); - err(__FUNCTION__": unable to save PCI configuration data, error %d\n", rc); + err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc); goto err_iounmap; } @@ -1188,6 +1196,8 @@ err_iounmap: iounmap(ctrl->hpc_reg); err_free_mem_region: release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); +err_free_bus: + kfree(ctrl->pci_bus); err_free_ctrl: kfree(ctrl); return rc; @@ -1328,6 +1338,8 @@ static void unload_cpqphpd(void) kfree(tres); } + kfree (ctrl->pci_bus); + tctrl = ctrl; ctrl = ctrl->next; kfree(tctrl); diff --git a/drivers/hotplug/cpqphp_ctrl.c b/drivers/hotplug/cpqphp_ctrl.c index f14f6dabe0b4..e30b88ac17f6 100644 --- a/drivers/hotplug/cpqphp_ctrl.c +++ b/drivers/hotplug/cpqphp_ctrl.c @@ -772,13 +772,13 @@ static struct pci_resource *get_resource (struct pci_resource **head, u32 size) return(NULL); for (node = *head; node; node = node->next) { - dbg(__FUNCTION__": req_size =%x node=%p, base=%x, length=%x\n", - size, node, node->base, node->length); + dbg("%s: req_size =%x node=%p, base=%x, length=%x\n", + __FUNCTION__, size, node, node->base, node->length); if (node->length < size) continue; if (node->base & (size - 1)) { - dbg(__FUNCTION__": not aligned\n"); + dbg("%s: not aligned\n", __FUNCTION__); // this one isn't base aligned properly // so we'll make a new entry and split it up temp_dword = (node->base | (size-1)) + 1; @@ -804,7 +804,7 @@ static struct pci_resource *get_resource (struct pci_resource **head, u32 size) // Don't need to check if too small since we already did if (node->length > size) { - dbg(__FUNCTION__": too big\n"); + dbg("%s: too big\n", __FUNCTION__); // this one is longer than we need // so we'll make a new entry and split it up split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); @@ -821,7 +821,7 @@ static struct pci_resource *get_resource (struct pci_resource **head, u32 size) node->next = split_node; } // End of too big on top end - dbg(__FUNCTION__": got one!!!\n"); + dbg("%s: got one!!!\n", __FUNCTION__); // If we got here, then it is the right size // Now take it out of the list if (*head == node) { @@ -856,7 +856,7 @@ int cpqhp_resource_sort_and_combine(struct pci_resource **head) struct pci_resource *node2; int out_of_order = 1; - dbg(__FUNCTION__": head = %p, *head = %p\n", head, *head); + dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head); if (!(*head)) return(1); @@ -942,7 +942,7 @@ void cpqhp_ctrl_intr(int IRQ, struct controller * ctrl, struct pt_regs *regs) // Read to clear posted writes misc = readw(ctrl->hpc_reg + MISC); - dbg (__FUNCTION__" - waking up\n"); + dbg ("%s - waking up\n", __FUNCTION__); wake_up_interruptible(&ctrl->queue); } @@ -1382,8 +1382,8 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) struct resource_lists res_lists; hp_slot = func->device - ctrl->slot_device_offset; - dbg(__FUNCTION__": func->device, slot_offset, hp_slot = %d, %d ,%d\n", - func->device, ctrl->slot_device_offset, hp_slot); + dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", + __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); if (ctrl->speed == 1) { // Wait for exclusive access to hardware @@ -1430,55 +1430,56 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) // turn on board and blink green LED // Wait for exclusive access to hardware - dbg(__FUNCTION__": before down\n"); + dbg("%s: before down\n", __FUNCTION__); down(&ctrl->crit_sect); - dbg(__FUNCTION__": after down\n"); + dbg("%s: after down\n", __FUNCTION__); - dbg(__FUNCTION__": before slot_enable\n"); + dbg("%s: before slot_enable\n", __FUNCTION__); slot_enable (ctrl, hp_slot); - dbg(__FUNCTION__": before green_LED_blink\n"); + dbg("%s: before green_LED_blink\n", __FUNCTION__); green_LED_blink (ctrl, hp_slot); - dbg(__FUNCTION__": before amber_LED_blink\n"); + dbg("%s: before amber_LED_blink\n", __FUNCTION__); amber_LED_off (ctrl, hp_slot); - dbg(__FUNCTION__": before set_SOGO\n"); + dbg("%s: before set_SOGO\n", __FUNCTION__); set_SOGO(ctrl); // Wait for SOBS to be unset - dbg(__FUNCTION__": before wait_for_ctrl_irq\n"); + dbg("%s: before wait_for_ctrl_irq\n", __FUNCTION__); wait_for_ctrl_irq (ctrl); - dbg(__FUNCTION__": after wait_for_ctrl_irq\n"); + dbg("%s: after wait_for_ctrl_irq\n", __FUNCTION__); // Done with exclusive hardware access - dbg(__FUNCTION__": before up\n"); + dbg("%s: before up\n", __FUNCTION__); up(&ctrl->crit_sect); - dbg(__FUNCTION__": after up\n"); + dbg("%s: after up\n", __FUNCTION__); // Wait for ~1 second because of hot plug spec - dbg(__FUNCTION__": before long_delay\n"); + dbg("%s: before long_delay\n", __FUNCTION__); long_delay(1*HZ); - dbg(__FUNCTION__": after long_delay\n"); + dbg("%s: after long_delay\n", __FUNCTION__); - dbg(__FUNCTION__": func status = %x\n", func->status); + dbg("%s: func status = %x\n", __FUNCTION__, func->status); // Check for a power fault if (func->status == 0xFF) { // power fault occurred, but it was benign temp_register = 0xFFFFFFFF; - dbg(__FUNCTION__": temp register set to %x by power fault\n", temp_register); + dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register); rc = POWER_FAILURE; func->status = 0; } else { // Get vendor/device ID u32 - rc = pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_VENDOR_ID, &temp_register); - dbg(__FUNCTION__": pci_read_config_dword returns %d\n", rc); - dbg(__FUNCTION__": temp_register is %x\n", temp_register); + ctrl->pci_bus->number = func->bus; + rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), PCI_VENDOR_ID, &temp_register); + dbg("%s: pci_read_config_dword returns %d\n", __FUNCTION__, rc); + dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register); if (rc != 0) { // Something's wrong here temp_register = 0xFFFFFFFF; - dbg(__FUNCTION__": temp register set to %x by error\n", temp_register); + dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register); } // Preset return code. It will be changed later if things go okay. rc = NO_ADAPTER_PRESENT; @@ -1494,7 +1495,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) rc = configure_new_device(ctrl, func, 0, &res_lists); - dbg(__FUNCTION__": back from configure_new_device\n"); + dbg("%s: back from configure_new_device\n", __FUNCTION__); ctrl->io_head = res_lists.io_head; ctrl->mem_head = res_lists.mem_head; ctrl->p_mem_head = res_lists.p_mem_head; @@ -1531,7 +1532,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) func->is_a_board = 0x01; //next, we will instantiate the linux pci_dev structures (with appropriate driver notification, if already present) - dbg(__FUNCTION__": configure linux pci_dev structure\n"); + dbg("%s: configure linux pci_dev structure\n", __FUNCTION__); index = 0; do { new_slot = cpqhp_slot_find(ctrl->bus, func->device, index++); @@ -1598,7 +1599,7 @@ static u32 remove_board(struct pci_func * func, u32 replace_flag, struct control device = func->device; hp_slot = func->device - ctrl->slot_device_offset; - dbg("In "__FUNCTION__", hp_slot = %d\n", hp_slot); + dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); // When we get here, it is safe to change base Address Registers. // We will attempt to save the base Address Register Lengths @@ -1927,7 +1928,7 @@ void cpqhp_pushbutton_thread (unsigned long slot) func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0); dbg("In power_down_board, func = %p, ctrl = %p\n", func, ctrl); if (!func) { - dbg("Error! func NULL in "__FUNCTION__"\n"); + dbg("Error! func NULL in %s\n", __FUNCTION__); return ; } @@ -1951,7 +1952,7 @@ void cpqhp_pushbutton_thread (unsigned long slot) func = cpqhp_slot_find(p_slot->bus, p_slot->device, 0); dbg("In add_board, func = %p, ctrl = %p\n", func, ctrl); if (!func) { - dbg("Error! func NULL in "__FUNCTION__"\n"); + dbg("Error! func NULL in %s\n", __FUNCTION__); return ; } @@ -2066,7 +2067,7 @@ int cpqhp_process_SI (struct controller *ctrl, struct pci_func *func) } if (rc) { - dbg(__FUNCTION__": rc = %d\n", rc); + dbg("%s: rc = %d\n", __FUNCTION__, rc); } if (p_slot) @@ -2082,7 +2083,9 @@ int cpqhp_process_SS (struct controller *ctrl, struct pci_func *func) u8 index = 0; u8 replace_flag; u32 rc = 0; + unsigned int devfn; struct slot* p_slot; + struct pci_bus *pci_bus = ctrl->pci_bus; int physical_slot=0; device = func->device; @@ -2094,8 +2097,11 @@ int cpqhp_process_SS (struct controller *ctrl, struct pci_func *func) // Make sure there are no video controllers here while (func && !rc) { + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + // Check the Class Code - rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, 0x0B, &class_code); + rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); if (rc) return rc; @@ -2104,13 +2110,13 @@ int cpqhp_process_SS (struct controller *ctrl, struct pci_func *func) rc = REMOVE_NOT_SUPPORTED; } else { // See if it's a bridge - rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type); + rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); if (rc) return rc; // If it's a bridge, check the VGA Enable bit if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { - rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_BRIDGE_CONTROL, &BCR); + rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR); if (rc) return rc; @@ -2332,11 +2338,12 @@ static u32 configure_new_device (struct controller * ctrl, struct pci_func * fun new_slot = func; - dbg(__FUNCTION__"\n"); + dbg("%s\n", __FUNCTION__); // Check for Multi-function device - rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, 0x0E, &temp_byte); + ctrl->pci_bus->number = func->bus; + rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte); if (rc) { - dbg(__FUNCTION__": rc = %d\n", rc); + dbg("%s: rc = %d\n", __FUNCTION__, rc); return rc; } @@ -2372,7 +2379,7 @@ static u32 configure_new_device (struct controller * ctrl, struct pci_func * fun // and creates a board structure while ((function < max_functions) && (!stop_it)) { - pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, function, 0x00, &ID); + pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID); if (ID == 0xFFFFFFFF) { // There's nothing there. function++; @@ -2435,6 +2442,7 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f u32 temp_register; u32 base; u32 ID; + unsigned int devfn; struct pci_resource *mem_node; struct pci_resource *p_mem_node; struct pci_resource *io_node; @@ -2445,17 +2453,22 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f struct pci_resource *hold_bus_node; struct irq_mapping irqs; struct pci_func *new_slot; + struct pci_bus *pci_bus; struct resource_lists temp_resources; + pci_bus = ctrl->pci_bus; + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + // Check for Bridge - rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &temp_byte); + rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte); if (rc) return rc; if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge // set Primary bus dbg("set Primary bus = %d\n", func->bus); - rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PRIMARY_BUS, func->bus); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_PRIMARY_BUS, func->bus); if (rc) return rc; @@ -2470,29 +2483,29 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f // set Secondary bus temp_byte = bus_node->base; dbg("set Secondary bus = %d\n", bus_node->base); - rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_SECONDARY_BUS, temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte); if (rc) return rc; // set subordinate bus temp_byte = bus_node->base + bus_node->length - 1; dbg("set subordinate bus = %d\n", bus_node->base + bus_node->length - 1); - rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_SUBORDINATE_BUS, temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); if (rc) return rc; // set subordinate Latency Timer and base Latency Timer temp_byte = 0x40; - rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_SEC_LATENCY_TIMER, temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte); if (rc) return rc; - rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_LATENCY_TIMER, temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte); if (rc) return rc; // set Cache Line size temp_byte = 0x08; - rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_CACHE_LINE_SIZE, temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte); if (rc) return rc; @@ -2568,10 +2581,10 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f // set IO base and Limit registers temp_byte = io_node->base >> 8; - rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_BASE, temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); temp_byte = (io_node->base + io_node->length - 1) >> 8; - rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_LIMIT, temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); } else { kfree(hold_IO_node); hold_IO_node = NULL; @@ -2586,16 +2599,16 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f // set Mem base and Limit registers temp_word = mem_node->base >> 16; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_BASE, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); temp_word = (mem_node->base + mem_node->length - 1) >> 16; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_LIMIT, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); } else { temp_word = 0xFFFF; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_BASE, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); temp_word = 0x0000; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_LIMIT, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); kfree(hold_mem_node); hold_mem_node = NULL; @@ -2610,16 +2623,16 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f // set Pre Mem base and Limit registers temp_word = p_mem_node->base >> 16; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_BASE, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); temp_word = (p_mem_node->base + p_mem_node->length - 1) >> 16; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_LIMIT, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); } else { temp_word = 0xFFFF; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_BASE, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); temp_word = 0x0000; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_LIMIT, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); kfree(hold_p_mem_node); hold_p_mem_node = NULL; @@ -2635,7 +2648,9 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f irqs.barber_pole = (irqs.barber_pole + 1) & 0x03; ID = 0xFFFFFFFF; - pci_read_config_dword_nodev (ctrl->pci_ops, hold_bus_node->base, device, 0, 0x00, &ID); + pci_bus->number = hold_bus_node->base; + pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), 0x00, &ID); + pci_bus->number = func->bus; if (ID != 0xFFFFFFFF) { // device Present // Setup slot structure. @@ -2703,7 +2718,7 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f temp_byte = temp_resources.bus_head->base - 1; // set subordinate bus - rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_SUBORDINATE_BUS, temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); if (temp_resources.bus_head->length == 0) { kfree(temp_resources.bus_head); @@ -2724,7 +2739,7 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f hold_IO_node->base = io_node->base + io_node->length; temp_byte = (hold_IO_node->base) >> 8; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_BASE, temp_byte); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_IO_BASE, temp_byte); return_resource(&(resources->io_head), io_node); } @@ -2742,13 +2757,13 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f func->io_head = hold_IO_node; temp_byte = (io_node->base - 1) >> 8; - rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_LIMIT, temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); return_resource(&(resources->io_head), io_node); } else { // it doesn't need any IO temp_word = 0x0000; - pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_LIMIT, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_IO_LIMIT, temp_word); return_resource(&(resources->io_head), io_node); kfree(hold_IO_node); @@ -2774,7 +2789,7 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f hold_mem_node->base = mem_node->base + mem_node->length; temp_word = (hold_mem_node->base) >> 16; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_BASE, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); return_resource(&(resources->mem_head), mem_node); } @@ -2792,14 +2807,14 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f // configure end address temp_word = (mem_node->base - 1) >> 16; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_LIMIT, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); // Return unused resources to the pool return_resource(&(resources->mem_head), mem_node); } else { // it doesn't need any Mem temp_word = 0x0000; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_LIMIT, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); return_resource(&(resources->mem_head), mem_node); kfree(hold_mem_node); @@ -2825,7 +2840,7 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f hold_p_mem_node->base = p_mem_node->base + p_mem_node->length; temp_word = (hold_p_mem_node->base) >> 16; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_BASE, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); return_resource(&(resources->p_mem_head), p_mem_node); } @@ -2843,13 +2858,13 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f func->p_mem_head = hold_p_mem_node; temp_word = (p_mem_node->base - 1) >> 16; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_LIMIT, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); return_resource(&(resources->p_mem_head), p_mem_node); } else { // it doesn't need any PMem temp_word = 0x0000; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_LIMIT, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); return_resource(&(resources->p_mem_head), p_mem_node); kfree(hold_p_mem_node); @@ -2870,14 +2885,14 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f // enable card command = 0x0157; // = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_COMMAND, command); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_COMMAND, command); // set Bridge Control Register command = 0x07; // = PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_NO_ISA - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_BRIDGE_CONTROL, command); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_BRIDGE_CONTROL, command); } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) { // Standard device - rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, 0x0B, &class_code); + rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); if (class_code == PCI_BASE_CLASS_DISPLAY) { // Display (video) adapter (not supported) @@ -2887,10 +2902,10 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f for (cloop = 0x10; cloop <= 0x24; cloop += 4) { temp_register = 0xFFFFFFFF; - dbg("CND: bus=%d, device=%d, func=%d, offset=%d\n", func->bus, func->device, func->function, cloop); - rc = pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register); + dbg("CND: bus=%d, devfn=%d, offset=%d\n", pci_bus->number, devfn, cloop); + rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); - rc = pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &temp_register); + rc = pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register); dbg("CND: base = 0x%x\n", temp_register); if (temp_register) { // If this register is implemented @@ -2971,7 +2986,7 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f return(NOT_ENOUGH_RESOURCES); } - rc = pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, base); + rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, base); // Check for 64-bit base if ((temp_register & 0x07L) == 0x04) { @@ -2980,13 +2995,13 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f // Upper 32 bits of address always zero on today's systems // FIXME this is probably not true on Alpha and ia64??? base = 0; - rc = pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, base); + rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, base); } } } // End of base register loop // Figure out which interrupt pin this function uses - rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_INTERRUPT_PIN, &temp_byte); + rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_INTERRUPT_PIN, &temp_byte); // If this function needs an interrupt and we are behind a bridge // and the pin is tied to something that's alread mapped, @@ -2998,7 +3013,7 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f IRQ = resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03]; } else { // Program IRQ based on card type - rc = pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, 0x0B, &class_code); + rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); if (class_code == PCI_BASE_CLASS_STORAGE) { IRQ = cpqhp_disk_irq; @@ -3008,7 +3023,7 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f } // IRQ Line - rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_INTERRUPT_LINE, IRQ); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ); if (!behind_bridge) { rc = cpqhp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ); @@ -3022,19 +3037,19 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f // Latency Timer temp_byte = 0x40; - rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_LATENCY_TIMER, temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte); // Cache Line size temp_byte = 0x08; - rc = pci_write_config_byte_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_CACHE_LINE_SIZE, temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte); // disable ROM base Address temp_dword = 0x00L; - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_ROM_ADDRESS, temp_dword); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_dword); // enable card temp_word = 0x0157; // = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR - rc = pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_COMMAND, temp_word); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_COMMAND, temp_word); } // End of Not-A-Bridge else else { // It's some strange type of PCI adapter (Cardbus?) diff --git a/drivers/hotplug/cpqphp_nvram.c b/drivers/hotplug/cpqphp_nvram.c index aafe9ee3aaa1..08dca3fba90c 100644 --- a/drivers/hotplug/cpqphp_nvram.c +++ b/drivers/hotplug/cpqphp_nvram.c @@ -161,7 +161,7 @@ static int check_for_compaq_ROM (void *rom_start) (temp6 == 'Q')) { result = 1; } - dbg (__FUNCTION__" - returned %d\n", result); + dbg ("%s - returned %d\n", __FUNCTION__, result); return result; } @@ -286,12 +286,12 @@ static u32 store_HRT (void *rom_start) return(rc); // The device Number - rc = add_byte( &pFill, ctrl->device, &usedbytes, &available); + rc = add_byte( &pFill, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available); if (rc) return(rc); // The function Number - rc = add_byte( &pFill, ctrl->function, &usedbytes, &available); + rc = add_byte( &pFill, PCI_FUNC(ctrl->pci_dev->devfn), &usedbytes, &available); if (rc) return(rc); @@ -479,8 +479,9 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl) device = p_ev_ctrl->device; function = p_ev_ctrl->function; - while ((bus != ctrl->bus) || (device != ctrl->device) - || (function != ctrl->function)) { + while ((bus != ctrl->bus) || + (device != PCI_SLOT(ctrl->pci_dev->devfn)) || + (function != PCI_FUNC(ctrl->pci_dev->devfn))) { nummem = p_ev_ctrl->mem_avail; numpmem = p_ev_ctrl->p_mem_avail; numio = p_ev_ctrl->io_avail; diff --git a/drivers/hotplug/cpqphp_pci.c b/drivers/hotplug/cpqphp_pci.c index d8c65c5af128..8b9b16589f3b 100644 --- a/drivers/hotplug/cpqphp_pci.c +++ b/drivers/hotplug/cpqphp_pci.c @@ -140,7 +140,7 @@ static int configure_visit_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct //We did not even find a hotplug rep of the function, create it //This code might be taken out if we can guarantee the creation of functions //in parallel (hotplug and Linux at the same time). - dbg("@@@@@@@@@@@ cpqhp_slot_create in "__FUNCTION__"\n"); + dbg("@@@@@@@@@@@ cpqhp_slot_create in %s\n", __FUNCTION__); temp_func = cpqhp_slot_create(bus->number); if (temp_func == NULL) return -ENOMEM; @@ -150,8 +150,9 @@ static int configure_visit_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct //Create /proc/bus/pci proc entry for this device and bus device is on //Notify the drivers of the change if (temp_func->pci_dev) { - pci_proc_attach_device(temp_func->pci_dev); - pci_announce_device_to_drivers(temp_func->pci_dev); +// pci_insert_device (temp_func->pci_dev, bus); +// pci_proc_attach_device(temp_func->pci_dev); +// pci_announce_device_to_drivers(temp_func->pci_dev); } return 0; @@ -307,7 +308,7 @@ int cpqhp_unconfigure_device(struct pci_func* func) memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped)); memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped)); - dbg(__FUNCTION__": bus/dev/func = %x/%x/%x\n",func->bus, func->device, func->function); + dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, func->device, func->function); for (j=0; j<8 ; j++) { struct pci_dev* temp = pci_find_slot(func->bus, (func->device << 3) | j); @@ -326,15 +327,15 @@ int cpqhp_unconfigure_device(struct pci_func* func) return rc; } -static int PCI_RefinedAccessConfig(struct pci_ops *ops, u8 bus, u8 device, u8 function, u8 offset, u32 *value) +static int PCI_RefinedAccessConfig(struct pci_bus *bus, unsigned int devfn, u8 offset, u32 *value) { u32 vendID = 0; - if (pci_read_config_dword_nodev (ops, bus, device, function, PCI_VENDOR_ID, &vendID) == -1) + if (pci_bus_read_config_dword (bus, devfn, PCI_VENDOR_ID, &vendID) == -1) return -1; if (vendID == 0xffffffff) return -1; - return pci_read_config_dword_nodev (ops, bus, device, function, offset, value); + return pci_bus_read_config_dword (bus, devfn, offset, value); } @@ -355,10 +356,10 @@ int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num) fakedev.devfn = dev_num << 3; fakedev.bus = &fakebus; fakebus.number = bus_num; - dbg(__FUNCTION__": dev %d, bus %d, pin %d, num %d\n", - dev_num, bus_num, int_pin, irq_num); + dbg("%s: dev %d, bus %d, pin %d, num %d\n", + __FUNCTION__, dev_num, bus_num, int_pin, irq_num); rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num); - dbg(__FUNCTION__":rc %d\n", rc); + dbg("%s: rc %d\n", __FUNCTION__, rc); if (rc) return rc; @@ -392,9 +393,11 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev u32 work; u8 tbus; + ctrl->pci_bus->number = bus_num; + for (tdevice = 0; tdevice < 0x100; tdevice++) { //Scan for access first - if (PCI_RefinedAccessConfig(ctrl->pci_ops, bus_num, tdevice >> 3, tdevice & 0x7, 0x08, &work) == -1) + if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1) continue; dbg("Looking for nonbridge bus_num %d dev_num %d\n", bus_num, tdevice); //Yep we got one. Not a bridge ? @@ -406,12 +409,12 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev } for (tdevice = 0; tdevice < 0x100; tdevice++) { //Scan for access first - if (PCI_RefinedAccessConfig(ctrl->pci_ops, bus_num, tdevice >> 3, tdevice & 0x7, 0x08, &work) == -1) + if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1) continue; dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice); //Yep we got one. bridge ? if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) { - pci_read_config_byte_nodev (ctrl->pci_ops, tbus, tdevice, 0, PCI_SECONDARY_BUS, &tbus); + pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(tdevice, 0), PCI_SECONDARY_BUS, &tbus); dbg("Recurse on bus_num %d tdevice %d\n", tbus, tdevice); if (PCI_ScanBusNonBridge(tbus, tdevice) == 0) return 0; @@ -450,19 +453,20 @@ static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num if (tslot == slot) { *bus_num = tbus; *dev_num = tdevice; - pci_read_config_dword_nodev (ctrl->pci_ops, *bus_num, *dev_num >> 3, *dev_num & 0x7, PCI_VENDOR_ID, &work); + ctrl->pci_bus->number = tbus; + pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_VENDOR_ID, &work); if (!nobridge || (work == 0xffffffff)) { if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength ); return 0; } - dbg("bus_num %d dev_num %d func_num %d\n", *bus_num, *dev_num >> 3, *dev_num & 0x7); - pci_read_config_dword_nodev (ctrl->pci_ops, *bus_num, *dev_num >> 3, *dev_num & 0x7, PCI_CLASS_REVISION, &work); + dbg("bus_num %d devfn %d\n", *bus_num, *dev_num); + pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_CLASS_REVISION, &work); dbg("work >> 8 (%x) = BRIDGE (%x)\n", work >> 8, PCI_TO_PCI_BRIDGE_CLASS); if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) { - pci_read_config_byte_nodev (ctrl->pci_ops, *bus_num, *dev_num >> 3, *dev_num & 0x7, PCI_SECONDARY_BUS, &tbus); + pci_bus_read_config_byte (ctrl->pci_bus, *dev_num, PCI_SECONDARY_BUS, &tbus); dbg("Scan bus for Non Bridge: bus %d\n", tbus); if (PCI_ScanBusForNonBridge(ctrl, tbus, dev_num) == 0) { *bus_num = tbus; @@ -535,17 +539,17 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug) } // Save PCI configuration space for all devices in supported slots - + ctrl->pci_bus->number = busnumber; for (device = FirstSupported; device <= LastSupported; device++) { ID = 0xFFFFFFFF; - rc = pci_read_config_dword_nodev (ctrl->pci_ops, busnumber, device, 0, PCI_VENDOR_ID, &ID); + rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID); if (ID != 0xFFFFFFFF) { // device in slot - rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, 0, 0x0B, &class_code); + rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code); if (rc) return rc; - rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, 0, PCI_HEADER_TYPE, &header_type); + rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type); if (rc) return rc; @@ -563,7 +567,7 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug) if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // P-P Bridge // Recurse the subordinate bus // get the subordinate bus number - rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, function, PCI_SECONDARY_BUS, &secondary_bus); + rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, function), PCI_SECONDARY_BUS, &secondary_bus); if (rc) { return rc; } else { @@ -572,9 +576,9 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug) // Save secondary bus cfg spc // with this recursive call. rc = cpqhp_save_config(ctrl, sub_bus, 0); - if (rc) return rc; + ctrl->pci_bus->number = busnumber; } } @@ -602,7 +606,7 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug) new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function); for (cloop = 0; cloop < 0x20; cloop++) { - rc = pci_read_config_dword_nodev (ctrl->pci_ops, busnumber, device, function, cloop << 2, (u32 *) & (new_slot-> config_space [cloop])); + rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop])); if (rc) return rc; } @@ -615,15 +619,15 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug) // reading in Class Code and Header type. while ((function < max_functions)&&(!stop_it)) { - rc = pci_read_config_dword_nodev (ctrl->pci_ops, busnumber, device, function, PCI_VENDOR_ID, &ID); + rc = pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID); if (ID == 0xFFFFFFFF) { // nothing there. function++; } else { // Something there - rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, function, 0x0B, &class_code); + rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, function), 0x0B, &class_code); if (rc) return rc; - rc = pci_read_config_byte_nodev (ctrl->pci_ops, busnumber, device, function, PCI_HEADER_TYPE, &header_type); + rc = pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(device, function), PCI_HEADER_TYPE, &header_type); if (rc) return rc; @@ -677,12 +681,12 @@ int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot) ID = 0xFFFFFFFF; - pci_read_config_dword_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, 0, PCI_VENDOR_ID, &ID); + ctrl->pci_bus->number = new_slot->bus; + pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID); if (ID != 0xFFFFFFFF) { // device in slot - pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, 0, 0x0B, &class_code); - - pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, 0, PCI_HEADER_TYPE, &header_type); + pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code); + pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type); if (header_type & 0x80) // Multi-function device max_functions = 8; @@ -694,22 +698,22 @@ int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot) do { if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge // Recurse the subordinate bus - pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, PCI_SECONDARY_BUS, &secondary_bus); + pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_SECONDARY_BUS, &secondary_bus); sub_bus = (int) secondary_bus; // Save the config headers for the secondary bus. rc = cpqhp_save_config(ctrl, sub_bus, 0); - if (rc) return(rc); + ctrl->pci_bus->number = new_slot->bus; } // End of IF new_slot->status = 0; for (cloop = 0; cloop < 0x20; cloop++) { - pci_read_config_dword_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, cloop << 2, (u32 *) & (new_slot-> config_space [cloop])); + pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop])); } function++; @@ -720,14 +724,14 @@ int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot) // reading in the Class Code and the Header type. while ((function < max_functions) && (!stop_it)) { - pci_read_config_dword_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, PCI_VENDOR_ID, &ID); + pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID); if (ID == 0xFFFFFFFF) { // nothing there. function++; } else { // Something there - pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, 0x0B, &class_code); + pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code); - pci_read_config_byte_nodev (ctrl->pci_ops, new_slot->bus, new_slot->device, function, PCI_HEADER_TYPE, &header_type); + pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, &header_type); stop_it++; } @@ -763,17 +767,21 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func) u32 rc; struct pci_func *next; int index = 0; + struct pci_bus *pci_bus = ctrl->pci_bus; + unsigned int devfn; func = cpqhp_slot_find(func->bus, func->device, index++); while (func != NULL) { + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); // Check for Bridge - pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type); + pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge - pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SECONDARY_BUS, &secondary_bus); + pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus); sub_bus = (int) secondary_bus; @@ -787,13 +795,14 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func) next = next->next; } + pci_bus->number = func->bus; //FIXME: this loop is duplicated in the non-bridge case. The two could be rolled together // Figure out IO and memory base lengths for (cloop = 0x10; cloop <= 0x14; cloop += 4) { temp_register = 0xFFFFFFFF; - pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register); - pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base); + pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); + pci_bus_read_config_dword (pci_bus, devfn, cloop, &base); if (base) { // If this register is implemented if (base & 0x01L) { @@ -827,8 +836,8 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func) // Figure out IO and memory base lengths for (cloop = 0x10; cloop <= 0x24; cloop += 4) { temp_register = 0xFFFFFFFF; - pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register); - pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base); + pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); + pci_bus_read_config_dword (pci_bus, devfn, cloop, &base); if (base) { // If this register is implemented if (base & 0x01L) { @@ -897,28 +906,31 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func) struct pci_resource *p_mem_node; struct pci_resource *io_node; struct pci_resource *bus_node; + struct pci_bus *pci_bus = ctrl->pci_bus; + unsigned int devfn; func = cpqhp_slot_find(func->bus, func->device, index++); while ((func != NULL) && func->is_a_board) { + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + // Save the command register - pci_read_config_word_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_COMMAND, &save_command); + pci_bus_read_config_word (pci_bus, devfn, PCI_COMMAND, &save_command); // disable card command = 0x00; - pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_COMMAND, command); + pci_bus_write_config_word (pci_bus, devfn, PCI_COMMAND, command); // Check for Bridge - pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type); + pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge // Clear Bridge Control Register command = 0x00; - pci_write_config_word_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_BRIDGE_CONTROL, command); - - pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SECONDARY_BUS, &secondary_bus); - - pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SUBORDINATE_BUS, &temp_byte); + pci_bus_write_config_word (pci_bus, devfn, PCI_BRIDGE_CONTROL, command); + pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus); + pci_bus_read_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte); bus_node =(struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); if (!bus_node) @@ -931,9 +943,8 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func) func->bus_head = bus_node; // Save IO base and Limit registers - pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_BASE, &b_base); - - pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_IO_LIMIT, &b_length); + pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_BASE, &b_base); + pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_LIMIT, &b_length); if ((b_base <= b_length) && (save_command & 0x01)) { io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); @@ -946,10 +957,10 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func) io_node->next = func->io_head; func->io_head = io_node; } - // Save memory base and Limit registers - pci_read_config_word_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_BASE, &w_base); - pci_read_config_word_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_MEMORY_LIMIT, &w_length); + // Save memory base and Limit registers + pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_BASE, &w_base); + pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length); if ((w_base <= w_length) && (save_command & 0x02)) { mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); @@ -962,10 +973,10 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func) mem_node->next = func->mem_head; func->mem_head = mem_node; } - // Save prefetchable memory base and Limit registers - pci_read_config_word_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_BASE, &w_base); - pci_read_config_word_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_PREF_MEMORY_LIMIT, &w_length); + // Save prefetchable memory base and Limit registers + pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base); + pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length); if ((w_base <= w_length) && (save_command & 0x02)) { p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); @@ -980,12 +991,11 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func) } // Figure out IO and memory base lengths for (cloop = 0x10; cloop <= 0x14; cloop += 4) { - pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &save_base); + pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base); temp_register = 0xFFFFFFFF; - pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register); - - pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base); + pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); + pci_bus_read_config_dword (pci_bus, devfn, cloop, &base); temp_register = base; @@ -1046,12 +1056,11 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func) } else if ((header_type & 0x7F) == 0x00) { // Standard header // Figure out IO and memory base lengths for (cloop = 0x10; cloop <= 0x24; cloop += 4) { - pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &save_base); + pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base); temp_register = 0xFFFFFFFF; - pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register); - - pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base); + pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); + pci_bus_read_config_dword (pci_bus, devfn, cloop, &base); temp_register = base; @@ -1138,21 +1147,26 @@ int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func) u32 temp; u32 rc; int index = 0; + struct pci_bus *pci_bus = ctrl->pci_bus; + unsigned int devfn; func = cpqhp_slot_find(func->bus, func->device, index++); while (func != NULL) { + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + // Start at the top of config space so that the control // registers are programmed last for (cloop = 0x3C; cloop > 0; cloop -= 4) { - pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, func->config_space[cloop >> 2]); + pci_bus_write_config_dword (pci_bus, devfn, cloop, func->config_space[cloop >> 2]); } - pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type); + pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); // If this is a bridge device, restore subordinate devices if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge - pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SECONDARY_BUS, &secondary_bus); + pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus); sub_bus = (int) secondary_bus; @@ -1172,7 +1186,7 @@ int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func) // they are the same. If not, the board is different. for (cloop = 16; cloop < 40; cloop += 4) { - pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &temp); + pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp); if (temp != func->config_space[cloop >> 2]) { dbg("Config space compare failure!!! offset = %x\n", cloop); @@ -1212,6 +1226,8 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func) u32 rc; struct pci_func *next; int index = 0; + struct pci_bus *pci_bus = ctrl->pci_bus; + unsigned int devfn; if (!func->is_a_board) return(ADD_NOT_SUPPORTED); @@ -1219,7 +1235,10 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func) func = cpqhp_slot_find(func->bus, func->device, index++); while (func != NULL) { - pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_VENDOR_ID, &temp_register); + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + pci_bus_read_config_dword (pci_bus, devfn, PCI_VENDOR_ID, &temp_register); // No adapter present if (temp_register == 0xFFFFFFFF) @@ -1229,14 +1248,14 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func) return(ADAPTER_NOT_SAME); // Check for same revision number and class code - pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_CLASS_REVISION, &temp_register); + pci_bus_read_config_dword (pci_bus, devfn, PCI_CLASS_REVISION, &temp_register); // Adapter not the same if (temp_register != func->config_space[0x08 >> 2]) return(ADAPTER_NOT_SAME); // Check for Bridge - pci_read_config_byte_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_HEADER_TYPE, &header_type); + pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { // PCI-PCI Bridge // In order to continue checking, we must program the @@ -1244,7 +1263,7 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func) // for it's subordinate bus(es) temp_register = func->config_space[0x18 >> 2]; - pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, PCI_PRIMARY_BUS, temp_register); + pci_bus_write_config_dword (pci_bus, devfn, PCI_PRIMARY_BUS, temp_register); secondary_bus = (temp_register >> 8) & 0xFF; @@ -1263,7 +1282,7 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func) // Check to see if it is a standard config header else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) { // Check subsystem vendor and ID - pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, PCI_SUBSYSTEM_VENDOR_ID, &temp_register); + pci_bus_read_config_dword (pci_bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &temp_register); if (temp_register != func->config_space[0x2C >> 2]) { // If it's a SMART-2 and the register isn't filled @@ -1277,10 +1296,8 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func) // Figure out IO and memory base lengths for (cloop = 0x10; cloop <= 0x24; cloop += 4) { temp_register = 0xFFFFFFFF; - pci_write_config_dword_nodev(ctrl->pci_ops, func->bus, func->device, func->function, cloop, temp_register); - - pci_read_config_dword_nodev (ctrl->pci_ops, func->bus, func->device, func->function, cloop, &base); - + pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); + pci_bus_read_config_dword (pci_bus, devfn, cloop, &base); if (base) { // If this register is implemented if (base & 0x01L) { // IO base @@ -1436,8 +1453,8 @@ int cpqhp_find_available_resources (struct controller *ctrl, void *rom_start) continue; } // find out if this entry is for an occupied slot - pci_read_config_dword_nodev (ctrl->pci_ops, primary_bus, dev_func >> 3, dev_func & 0x07, PCI_VENDOR_ID, &temp_dword); - + ctrl->pci_bus->number = primary_bus; + pci_bus_read_config_dword (ctrl->pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword); dbg("temp_D_word = %x\n", temp_dword); if (temp_dword != 0xFFFFFFFF) { @@ -1586,7 +1603,7 @@ int cpqhp_return_board_resources(struct pci_func * func, struct resource_lists * int rc = 0; struct pci_resource *node; struct pci_resource *t_node; - dbg(__FUNCTION__"\n"); + dbg("%s\n", __FUNCTION__); if (!func) return(1); diff --git a/drivers/hotplug/cpqphp_proc.c b/drivers/hotplug/cpqphp_proc.c index 64b3461a6e20..8912f881664a 100644 --- a/drivers/hotplug/cpqphp_proc.c +++ b/drivers/hotplug/cpqphp_proc.c @@ -53,8 +53,9 @@ static int read_ctrl (char *buf, char **start, off_t offset, int len, int *eof, *eof = 1; out += sprintf(out, "hot plug ctrl Info Page\n"); - out += sprintf(out, "bus = %d, device = %d, function = %d\n",ctrl->bus, - ctrl->device, ctrl->function); + out += sprintf(out, "bus = %d, device = %d, function = %d\n", + ctrl->bus, PCI_SLOT(ctrl->pci_dev->devfn), + PCI_FUNC(ctrl->pci_dev->devfn)); out += sprintf(out, "Free resources: memory\n"); index = 11; res = ctrl->mem_head; @@ -104,8 +105,9 @@ static int read_dev (char *buf, char **start, off_t offset, int len, int *eof, v *eof = 1; out += sprintf(out, "hot plug ctrl Info Page\n"); - out += sprintf(out, "bus = %d, device = %d, function = %d\n",ctrl->bus, - ctrl->device, ctrl->function); + out += sprintf(out, "bus = %d, device = %d, function = %d\n", + ctrl->bus, PCI_SLOT(ctrl->pci_dev->devfn), + PCI_FUNC(ctrl->pci_dev->devfn)); slot=ctrl->slot; diff --git a/drivers/hotplug/ibmphp.h b/drivers/hotplug/ibmphp.h index ca8e5044c622..fc899b307834 100644 --- a/drivers/hotplug/ibmphp.h +++ b/drivers/hotplug/ibmphp.h @@ -39,7 +39,8 @@ extern int ibmphp_debug; #else #define MY_NAME THIS_MODULE->name #endif -#define debug(fmt, arg...) do { if (ibmphp_debug) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0) +#define debug(fmt, arg...) do { if (ibmphp_debug == 1) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0) +#define debug_pci(fmt, arg...) do { if (ibmphp_debug) printk(KERN_DEBUG "%s: " fmt , MY_NAME , ## arg); } while (0) #define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg) #define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg) @@ -121,6 +122,7 @@ struct scal_detail { u8 port1_port_connect; u8 port2_node_connect; u8 port2_port_connect; + u8 chassis_num; // struct list_head scal_detail_list; }; @@ -139,9 +141,27 @@ struct rio_detail { u8 port1_port_connect; u8 first_slot_num; u8 status; -// struct list_head rio_detail_list; + u8 wpindex; + u8 chassis_num; + struct list_head rio_detail_list; }; +struct opt_rio { + u8 rio_type; + u8 chassis_num; + u8 first_slot_num; + u8 middle_num; + struct list_head opt_rio_list; +}; + +struct opt_rio_lo { + u8 rio_type; + u8 chassis_num; + u8 first_slot_num; + u8 middle_num; + u8 pack_count; + struct list_head opt_rio_lo_list; +}; /**************************************************************** * HPC DESCRIPTOR NODE * @@ -153,7 +173,6 @@ struct ebda_hpc_list { short phys_addr; // struct list_head ebda_hpc_list; }; - /***************************************************************** * IN HPC DATA STRUCTURE, THE ASSOCIATED SLOT AND BUS * * STRUCTURE * @@ -195,6 +214,9 @@ struct wpeg_i2c_ctlr_access { u8 i2c_addr; }; +#define HPC_DEVICE_ID 0x0246 +#define HPC_SUBSYSTEM_ID 0x0247 +#define HPC_PCI_OFFSET 0x40 /************************************************************************* * RSTC DESCRIPTOR NODE * *************************************************************************/ @@ -215,8 +237,9 @@ struct ebda_pci_rsrc { u8 rsrc_type; u8 bus_num; u8 dev_fun; - ulong start_addr; - ulong end_addr; + u32 start_addr; + u32 end_addr; + u8 marked; /* for NVRAM */ struct list_head ebda_pci_rsrc_list; }; @@ -248,7 +271,7 @@ struct bus_info { ***********************************************************/ extern struct list_head ibmphp_ebda_pci_rsrc_head; extern struct list_head ibmphp_slot_head; - +extern struct list_head ibmphp_res_head; /*********************************************************** * FUNCTION PROTOTYPES * ***********************************************************/ @@ -263,6 +286,7 @@ extern void ibmphp_free_ebda_pci_rsrc_queue (void); extern struct bus_info *ibmphp_find_same_bus_num (u32); extern int ibmphp_get_bus_index (u8); extern u16 ibmphp_get_total_controllers (void); +extern int ibmphp_register_pci (void); /* passed parameters */ #define MEM 0 @@ -669,7 +693,7 @@ extern void ibmphp_hpc_stop_poll_thread (void); #define PCIX66 0x05 #define PCI66 0x04 -extern struct pci_ops *ibmphp_pci_root_ops; +extern struct pci_bus *ibmphp_pci_bus; /* Variables */ @@ -713,6 +737,7 @@ struct slot { struct controller { struct ebda_hpc_slot *slots; struct ebda_hpc_bus *buses; + struct pci_dev *ctrl_dev; /* in case where controller is PCI */ u8 starting_slot_num; /* starting and ending slot #'s this ctrl controls*/ u8 ending_slot_num; u8 revision; diff --git a/drivers/hotplug/ibmphp_core.c b/drivers/hotplug/ibmphp_core.c index 87234e42f58e..5113d30f93f1 100644 --- a/drivers/hotplug/ibmphp_core.c +++ b/drivers/hotplug/ibmphp_core.c @@ -44,7 +44,7 @@ #define get_ctrl_revision(sl, rev) ibmphp_hpc_readslot (sl, READ_REVLEVEL, rev) #define get_hpc_options(sl, opt) ibmphp_hpc_readslot (sl, READ_HPCOPTIONS, opt) -#define DRIVER_VERSION "0.3" +#define DRIVER_VERSION "0.6" #define DRIVER_DESC "IBM Hot Plug PCI Controller Driver" int ibmphp_debug; @@ -56,7 +56,7 @@ MODULE_LICENSE ("GPL"); MODULE_DESCRIPTION (DRIVER_DESC); static int *ops[MAX_OPS + 1]; -struct pci_ops *ibmphp_pci_root_ops; +struct pci_bus *ibmphp_pci_bus; static int max_slots; static int irqs[16]; /* PIC mode IRQ's we're using so far (in case MPS tables don't provide default info for empty slots */ @@ -88,6 +88,8 @@ static inline int get_cur_bus_info (struct slot **sl) slot_cur->bus_on->current_speed = CURRENT_BUS_SPEED (slot_cur->busstatus); if (READ_BUS_MODE (slot_cur->ctrl)) slot_cur->bus_on->current_bus_mode = CURRENT_BUS_MODE (slot_cur->busstatus); + else + slot_cur->bus_on->current_bus_mode = 0xFF; debug ("busstatus = %x, bus_speed = %x, bus_mode = %x\n", slot_cur->busstatus, slot_cur->bus_on->current_speed, slot_cur->bus_on->current_bus_mode); @@ -108,11 +110,15 @@ static inline int slot_update (struct slot **sl) static int __init get_max_slots (void) { + struct slot * slot_cur; struct list_head * tmp; - int slot_count = 0; + u8 slot_count = 0; - list_for_each (tmp, &ibmphp_slot_head) - ++slot_count; + list_for_each (tmp, &ibmphp_slot_head) { + slot_cur = list_entry (tmp, struct slot, ibm_slot_list); + /* sometimes the hot-pluggable slots start with 4 (not always from 1 */ + slot_count = max (slot_count, slot_cur->number); + } return slot_count; } @@ -330,7 +336,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 * value) memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot)); hpcrc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &(myslot.status)); if (!hpcrc) { - *value = SLOT_POWER (myslot.status); + *value = SLOT_PWRGD (myslot.status); rc = 0; } } @@ -394,15 +400,22 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, u8 * value) if (pslot) { rc = 0; mode = pslot->supported_bus_mode; - *value = pslot->supported_speed; - *value &= 0x0f; - - if (mode == BUS_MODE_PCIX) - *value |= 0x80; - else if (mode == BUS_MODE_PCI) - *value |= 0x40; - else - *value |= 0x20; + *value = pslot->supported_speed; + switch (*value) { + case BUS_SPEED_33: + break; + case BUS_SPEED_66: + if (mode == BUS_MODE_PCIX) + *value += 0x01; + break; + case BUS_SPEED_100: + case BUS_SPEED_133: + *value = pslot->supported_speed + 0x01; + break; + default: +*/ /* Note (will need to change): there would be soon 256, 512 also */ +/* rc = -ENODEV; + } } } else rc = -ENODEV; @@ -429,14 +442,25 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, u8 * value) if (!rc) { mode = pslot->bus_on->current_bus_mode; *value = pslot->bus_on->current_speed; - *value &= 0x0f; - - if (mode == BUS_MODE_PCIX) - *value |= 0x80; - else if (mode == BUS_MODE_PCI) - *value |= 0x40; - else - *value |= 0x20; + switch (*value) { + case BUS_SPEED_33: + break; + case BUS_SPEED_66: + if (mode == BUS_MODE_PCIX) + *value += 0x01; + else if (mode == BUS_MODE_PCI) + ; + else + *value = PCI_SPEED_UNKNOWN; + break; + case BUS_SPEED_100: + case BUS_SPEED_133: + *value += 0x01; + break; + default: +*/ /* Note of change: there would also be 256, 512 soon */ +/* rc = -ENODEV; + } } } } else @@ -454,7 +478,7 @@ static int get_max_adapter_speed_1 (struct hotplug_slot *hotplug_slot, u8 * valu int hpcrc = 0; struct slot myslot; - debug ("get_max_adapter_speed - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong)hotplug_slot, (ulong) value); + debug ("get_max_adapter_speed_1 - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong)hotplug_slot, (ulong) value); if (flag) ibmphp_lock_operations (); @@ -485,17 +509,16 @@ static int get_max_adapter_speed_1 (struct hotplug_slot *hotplug_slot, u8 * valu if (flag) ibmphp_unlock_operations (); - debug ("get_adapter_present - Exit rc[%d] hpcrc[%x] value[%x]\n", rc, hpcrc, *value); + debug ("get_max_adapter_speed_1 - Exit rc[%d] hpcrc[%x] value[%x]\n", rc, hpcrc, *value); return rc; } -static int get_card_bus_names (struct hotplug_slot *hotplug_slot, char * value) +static int get_bus_name (struct hotplug_slot *hotplug_slot, char * value) { int rc = -ENODEV; struct slot *pslot = NULL; - struct pci_dev * dev = NULL; - debug ("get_card_bus_names - Entry hotplug_slot[%lx] \n", (ulong)hotplug_slot); + debug ("get_bus_name - Entry hotplug_slot[%lx] \n", (ulong)hotplug_slot); ibmphp_lock_operations (); @@ -503,26 +526,17 @@ static int get_card_bus_names (struct hotplug_slot *hotplug_slot, char * value) pslot = (struct slot *) hotplug_slot->private; if (pslot) { rc = 0; - if (pslot->func) - dev = pslot->func->dev; - else - dev = pci_find_slot (pslot->bus, (pslot->device << 3) | (0x00 & 0x7)); - if (dev) - snprintf (value, 100, "Bus %d : %s", pslot->bus,dev->name); - else - snprintf (value, 100, "Bus %d", pslot->bus); - - + snprintf (value, 100, "Bus %x", pslot->bus); } } else rc = -ENODEV; ibmphp_unlock_operations (); - debug ("get_card_bus_names - Exit rc[%d] value[%x]\n", rc, *value); + debug ("get_bus_name - Exit rc[%d] value[%x]\n", rc, *value); return rc; } - */ + /******************************************************************************* * This routine will initialize the ops data structure used in the validate * function. It will also power off empty slots that are powered on since BIOS @@ -531,12 +545,14 @@ static int get_card_bus_names (struct hotplug_slot *hotplug_slot, char * value) static int __init init_ops (void) { struct slot *slot_cur; + struct list_head *tmp; int retval; - int j; int rc; + int j; for (j = 0; j < MAX_OPS; j++) { ops[j] = (int *) kmalloc ((max_slots + 1) * sizeof (int), GFP_KERNEL); + memset (ops[j], 0, (max_slots + 1) * sizeof (int)); if (!ops[j]) { err ("out of system memory \n"); return -ENOMEM; @@ -547,12 +563,13 @@ static int __init init_ops (void) ops[REMOVE][0] = 0; ops[DETAIL][0] = 0; - for (j = 1; j <= max_slots; j++) { + list_for_each (tmp, &ibmphp_slot_head) { + slot_cur = list_entry (tmp, struct slot, ibm_slot_list); - slot_cur = ibmphp_get_slot_from_physical_num (j); + if (!slot_cur) + return -ENODEV; debug ("BEFORE GETTING SLOT STATUS, slot # %x\n", slot_cur->number); - if (slot_cur->ctrl->revision == 0xFF) if (get_ctrl_revision (slot_cur, &slot_cur->ctrl->revision)) return -1; @@ -572,21 +589,21 @@ static int __init init_ops (void) debug ("status = %x, ext_status = %x\n", slot_cur->status, slot_cur->ext_status); debug ("SLOT_POWER = %x, SLOT_PRESENT = %x, SLOT_LATCH = %x\n", SLOT_POWER (slot_cur->status), SLOT_PRESENT (slot_cur->status), SLOT_LATCH (slot_cur->status)); - if (!(SLOT_POWER (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) + if (!(SLOT_PWRGD (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) /* No power, adapter, and latch closed */ - ops[ADD][j] = 1; + ops[ADD][slot_cur->number] = 1; else - ops[ADD][j] = 0; + ops[ADD][slot_cur->number] = 0; - ops[DETAIL][j] = 1; + ops[DETAIL][slot_cur->number] = 1; - if ((SLOT_POWER (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) + if ((SLOT_PWRGD (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) /*Power,adapter,latch closed */ - ops[REMOVE][j] = 1; + ops[REMOVE][slot_cur->number] = 1; else - ops[REMOVE][j] = 0; + ops[REMOVE][slot_cur->number] = 0; - if ((SLOT_POWER (slot_cur->status)) && !(SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) { + if ((SLOT_PWRGD (slot_cur->status)) && !(SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) { debug ("BEFORE POWER OFF COMMAND\n"); rc = power_off (slot_cur); if (rc) @@ -624,7 +641,7 @@ static int validate (struct slot *slot_cur, int opn) if (retval) return retval; - if (!(SLOT_POWER (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) + if (!(SLOT_PWRGD (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) ops[ADD][number] = 1; else @@ -632,7 +649,7 @@ static int validate (struct slot *slot_cur, int opn) ops[DETAIL][number] = 1; - if ((SLOT_POWER (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) + if ((SLOT_PWRGD (slot_cur->status)) && (SLOT_PRESENT (slot_cur->status)) && !(SLOT_LATCH (slot_cur->status))) ops[REMOVE][number] = 1; else @@ -678,7 +695,7 @@ int ibmphp_update_slot_info (struct slot *slot_cur) } snprintf (buffer, 10, "%d", slot_cur->number); - info->power_status = SLOT_POWER (slot_cur->status); + info->power_status = SLOT_PWRGD (slot_cur->status); info->attention_status = SLOT_ATTN (slot_cur->status, slot_cur->ext_status); info->latch_status = SLOT_LATCH (slot_cur->status); if (!SLOT_PRESENT (slot_cur->status)) { @@ -688,8 +705,8 @@ int ibmphp_update_slot_info (struct slot *slot_cur) info->adapter_status = 1; // get_max_adapter_speed_1 (slot_cur->hotplug_slot, &info->max_adapter_speed_status, 0); } -/* - bus_speed = slot_cur->bus_on->current_speed; + /* !!!!!!!!!TO DO: THIS NEEDS TO CHANGE!!!!!!!!!!!!! */ +/* bus_speed = slot_cur->bus_on->current_speed; bus_speed &= 0x0f; if (slot_cur->bus_on->current_bus_mode == BUS_MODE_PCIX) @@ -701,7 +718,7 @@ int ibmphp_update_slot_info (struct slot *slot_cur) info->cur_bus_speed_status = bus_speed; info->max_bus_speed_status = slot_cur->hotplug_slot->info->max_bus_speed_status; - // To do: card_bus_names + // To do: bus_names */ rc = pci_hp_change_slot_info (buffer, info); kfree (info); @@ -752,18 +769,6 @@ static struct pci_bus *find_bus (u8 busno) return NULL; } -/****************************************************************** - * This function is here because we can no longer use pci_root_ops - ******************************************************************/ -static struct pci_ops *get_root_pci_ops (void) -{ - struct pci_bus * bus; - - if ((bus = find_bus (0))) - return bus->ops; - return NULL; -} - /************************************************************* * This routine frees up memory used by struct slot, including * the pointers to pci_func, bus, hotplug_slot, controller, @@ -775,8 +780,10 @@ static void free_slots (void) struct list_head * tmp; struct list_head * next; - list_for_each_safe (tmp, next, &ibmphp_slot_head) { + debug ("%s -- enter\n", __FUNCTION__); + list_for_each_safe (tmp, next, &ibmphp_slot_head) { + slot_cur = list_entry (tmp, struct slot, ibm_slot_list); pci_hp_deregister (slot_cur->hotplug_slot); @@ -795,7 +802,9 @@ static void free_slots (void) ibmphp_unconfigure_card (&slot_cur, -1); /* we don't want to actually remove the resources, since free_resources will do just that */ kfree (slot_cur); + slot_cur = NULL; } + debug ("%s -- exit\n", __FUNCTION__); } static int ibm_is_pci_dev_in_use (struct pci_dev *dev) @@ -851,7 +860,7 @@ static int ibm_unconfigure_visit_pci_dev_phase2 (struct pci_dev_wrapped *wrapped if (temp_func) temp_func->dev = NULL; else - err ("No pci_func representation for bus, devfn = %d, %x\n", dev->bus->number, dev->devfn); + debug ("No pci_func representation for bus, devfn = %d, %x\n", dev->bus->number, dev->devfn); return 0; } @@ -954,8 +963,8 @@ static int configure_visit_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct } if (temp_func->dev) { - pci_proc_attach_device (temp_func->dev); - pci_announce_device_to_drivers (temp_func->dev); +// pci_proc_attach_device (temp_func->dev); +// pci_announce_device_to_drivers (temp_func->dev); } return 0; @@ -965,6 +974,51 @@ static struct pci_visit configure_functions = { .visit_pci_dev =configure_visit_pci_dev, }; + +/* + * The following function is to fix kernel bug regarding + * getting bus entries, here we manually add those primary + * bus entries to kernel bus structure whenever apply + */ + +static u8 bus_structure_fixup (u8 busno) +{ + struct pci_bus *bus; + struct pci_dev *dev; + u16 l; + + if (!find_bus (busno) || !(ibmphp_find_same_bus_num (busno))) + return 1; + + bus = kmalloc (sizeof (*bus), GFP_KERNEL); + if (!bus) { + err ("%s - out of memory\n", __FUNCTION__); + return 1; + } + dev = kmalloc (sizeof (*dev), GFP_KERNEL); + if (!dev) { + kfree (bus); + err ("%s - out of memory\n", __FUNCTION__); + return 1; + } + + bus->number = busno; + bus->ops = ibmphp_pci_bus->ops; + dev->bus = bus; + for (dev->devfn = 0; dev->devfn < 256; dev->devfn += 8) { + if (!pci_read_config_word (dev, PCI_VENDOR_ID, &l) && l != 0x0000 && l != 0xffff) { + debug ("%s - Inside bus_struture_fixup() \n", __FUNCTION__); + pci_scan_bus (busno, ibmphp_pci_bus->ops, NULL); + break; + } + } + + kfree (dev); + kfree (bus); + + return 0; +} + static int ibm_configure_device (struct pci_func *func) { unsigned char bus; @@ -972,6 +1026,7 @@ static int ibm_configure_device (struct pci_func *func) struct pci_bus *child; struct pci_dev *temp; int rc = 0; + int flag = 0; /* this is to make sure we don't double scan the bus, for bridged devices primarily */ struct pci_dev_wrapped wrapped_dev; struct pci_bus_wrapped wrapped_bus; @@ -980,6 +1035,8 @@ static int ibm_configure_device (struct pci_func *func) memset (&wrapped_bus, 0, sizeof (struct pci_bus_wrapped)); memset (&dev0, 0, sizeof (struct pci_dev)); + if (!(bus_structure_fixup (func->busno))) + flag = 1; if (func->dev == NULL) func->dev = pci_find_slot (func->busno, (func->device << 3) | (func->function & 0x7)); @@ -995,7 +1052,7 @@ static int ibm_configure_device (struct pci_func *func) return 0; } } - if (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) { pci_read_config_byte (func->dev, PCI_SECONDARY_BUS, &bus); child = (struct pci_bus *) pci_add_new_bus (func->dev->bus, (func->dev), bus); pci_do_scan_bus (child); @@ -1028,7 +1085,7 @@ static int is_bus_empty (struct slot * slot_cur) rc = slot_update (&tmp_slot); if (rc) return 0; - if (SLOT_PRESENT (tmp_slot->status) && SLOT_POWER (tmp_slot->status)) + if (SLOT_PRESENT (tmp_slot->status) && SLOT_PWRGD (tmp_slot->status)) return 0; i++; } @@ -1046,6 +1103,9 @@ static int set_bus (struct slot * slot_cur) int rc; u8 speed; u8 cmd = 0x0; + const struct list_head *tmp; + struct pci_dev * dev; + int retval; debug ("%s - entry slot # %d \n", __FUNCTION__, slot_cur->number); if (SET_BUS_STATUS (slot_cur->ctrl) && is_bus_empty (slot_cur)) { @@ -1091,6 +1151,14 @@ static int set_bus (struct slot * slot_cur) cmd = HPC_BUS_100PCIXMODE; break; case BUS_SPEED_133: + /* This is to take care of the bug in CIOBX chip*/ + list_for_each (tmp, &pci_devices) { + dev = (struct pci_dev *) pci_dev_g (tmp); + if (dev) { + if ((dev->vendor == 0x1166) && (dev->device == 0x0101)) + ibmphp_hpc_writeslot (slot_cur, HPC_BUS_100PCIXMODE); + } + } cmd = HPC_BUS_133PCIXMODE; break; default: @@ -1103,9 +1171,17 @@ static int set_bus (struct slot * slot_cur) return -ENODEV; } debug ("setting bus speed for slot %d, cmd %x\n", slot_cur->number, cmd); - ibmphp_hpc_writeslot (slot_cur, cmd); + retval = ibmphp_hpc_writeslot (slot_cur, cmd); + if (retval) { + err ("setting bus speed failed\n"); + return retval; + } + if (CTLR_RESULT (slot_cur->ctrl->status)) { + err ("command not completed successfully in set_bus \n"); + return -EIO; + } } - /* This is for x400, once Brandon fixes the firmware, + /* This is for x440, once Brandon fixes the firmware, will not need this delay */ long_delay (1 * HZ); debug ("%s -Exit \n", __FUNCTION__); @@ -1128,7 +1204,7 @@ static int check_limitations (struct slot *slot_cur) for (i = slot_cur->bus_on->slot_min; i <= slot_cur->bus_on->slot_max; i++) { tmp_slot = ibmphp_get_slot_from_physical_num (i); - if ((SLOT_POWER (tmp_slot->status)) && !(SLOT_CONNECT (tmp_slot->status))) + if ((SLOT_PWRGD (tmp_slot->status)) && !(SLOT_CONNECT (tmp_slot->status))) count++; } get_cur_bus_info (&slot_cur); @@ -1384,11 +1460,15 @@ int ibmphp_disable_slot (struct hotplug_slot *hotplug_slot) debug ("DISABLING SLOT... \n"); - if (slot_cur == NULL) + if (slot_cur == NULL) { + ibmphp_unlock_operations (); return -ENODEV; + } - if (slot_cur->ctrl == NULL) + if (slot_cur->ctrl == NULL) { + ibmphp_unlock_operations (); return -ENODEV; + } flag = slot_cur->flag; /* to see if got here from polling */ @@ -1463,7 +1543,8 @@ int ibmphp_disable_slot (struct hotplug_slot *hotplug_slot) return -EFAULT; } - ibmphp_update_slot_info (slot_cur); + if (flag) + ibmphp_update_slot_info (slot_cur); ibmphp_unlock_operations (); return -EFAULT; } @@ -1503,10 +1584,10 @@ struct hotplug_slot_ops ibmphp_hotplug_slot_ops = { .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_present, -/* get_max_bus_speed_status: get_max_bus_speed, +/* .get_max_bus_speed_status = get_max_bus_speed, .get_max_adapter_speed_status = get_max_adapter_speed, .get_cur_bus_speed_status = get_cur_bus_speed, - .get_card_bus_names_status = get_card_bus_names, + .get_bus_name_status = get_bus_name, */ }; @@ -1526,6 +1607,7 @@ static void ibmphp_unload (void) static int __init ibmphp_init (void) { + struct pci_bus *bus; int i = 0; int rc = 0; @@ -1533,12 +1615,19 @@ static int __init ibmphp_init (void) info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); - ibmphp_pci_root_ops = get_root_pci_ops (); - if (ibmphp_pci_root_ops == NULL) { - err ("cannot read bus operations... will not be able to read the cards. Please check your system\n"); - return -ENODEV; + ibmphp_pci_bus = kmalloc (sizeof (*ibmphp_pci_bus), GFP_KERNEL); + if (!ibmphp_pci_bus) { + err ("out of memory\n"); + return -ENOMEM; } + bus = find_bus (0); + if (!bus) { + err ("Can't find the root pci bus, can not continue\n"); + return -ENODEV; + } + memcpy (ibmphp_pci_bus, bus, sizeof (*ibmphp_pci_bus)); + ibmphp_debug = debug; ibmphp_hpc_initvars (); @@ -1559,6 +1648,11 @@ static int __init ibmphp_init (void) debug ("AFTER Resource & EBDA INITIALIZATIONS\n"); max_slots = get_max_slots (); + + if ((rc = ibmphp_register_pci ())) { + ibmphp_unload (); + return rc; + } if (init_ops ()) { ibmphp_unload (); @@ -1570,11 +1664,9 @@ static int __init ibmphp_init (void) return -ENODEV; } - /* lock ourselves into memory with a module count of -1 - * so that no one can unload us. */ + /* if no NVRAM module selected, lock ourselves into memory with a + * module count of -1 so that no one can unload us. */ MOD_DEC_USE_COUNT; - - return 0; } diff --git a/drivers/hotplug/ibmphp_ebda.c b/drivers/hotplug/ibmphp_ebda.c index de180f16e01a..86a88433da5f 100644 --- a/drivers/hotplug/ibmphp_ebda.c +++ b/drivers/hotplug/ibmphp_ebda.c @@ -56,11 +56,17 @@ LIST_HEAD (ibmphp_slot_head); /* Local variables */ static struct ebda_hpc_list *hpc_list_ptr; static struct ebda_rsrc_list *rsrc_list_ptr; -static struct rio_table_hdr *rio_table_ptr; +static struct rio_table_hdr *rio_table_ptr = NULL; static LIST_HEAD (ebda_hpc_head); static LIST_HEAD (bus_info_head); +static LIST_HEAD (rio_vg_head); +static LIST_HEAD (rio_lo_head); +static LIST_HEAD (opt_vg_head); +static LIST_HEAD (opt_lo_head); static void *io_mem; +char *chassis_str, *rxe_str, *str; + /* Local functions */ static int ebda_rsrc_controller (void); static int ebda_rsrc_rsrc (void); @@ -125,6 +131,7 @@ static void free_ebda_hpc (struct controller *controller) controller->slots = NULL; kfree (controller->buses); controller->buses = NULL; + controller->ctrl_dev = NULL; kfree (controller); } @@ -173,18 +180,77 @@ static void __init print_bus_info (void) } } -static void print_ebda_pci_rsrc (void) +static void print_lo_info (void) +{ + struct rio_detail *ptr; + struct list_head *ptr1; + debug ("print_lo_info ---- \n"); + list_for_each (ptr1, &rio_lo_head) { + ptr = list_entry (ptr1, struct rio_detail, rio_detail_list); + debug ("%s - rio_node_id = %x\n", __FUNCTION__, ptr->rio_node_id); + debug ("%s - rio_type = %x\n", __FUNCTION__, ptr->rio_type); + debug ("%s - owner_id = %x\n", __FUNCTION__, ptr->owner_id); + debug ("%s - first_slot_num = %x\n", __FUNCTION__, ptr->first_slot_num); + debug ("%s - wpindex = %x\n", __FUNCTION__, ptr->wpindex); + debug ("%s - chassis_num = %x\n", __FUNCTION__, ptr->chassis_num); + + } +} + +static void print_vg_info (void) +{ + struct rio_detail *ptr; + struct list_head *ptr1; + debug ("%s --- \n", __FUNCTION__); + list_for_each (ptr1, &rio_vg_head) { + ptr = list_entry (ptr1, struct rio_detail, rio_detail_list); + debug ("%s - rio_node_id = %x\n", __FUNCTION__, ptr->rio_node_id); + debug ("%s - rio_type = %x\n", __FUNCTION__, ptr->rio_type); + debug ("%s - owner_id = %x\n", __FUNCTION__, ptr->owner_id); + debug ("%s - first_slot_num = %x\n", __FUNCTION__, ptr->first_slot_num); + debug ("%s - wpindex = %x\n", __FUNCTION__, ptr->wpindex); + debug ("%s - chassis_num = %x\n", __FUNCTION__, ptr->chassis_num); + + } +} + +static void __init print_ebda_pci_rsrc (void) { struct ebda_pci_rsrc *ptr; struct list_head *ptr1; list_for_each (ptr1, &ibmphp_ebda_pci_rsrc_head) { ptr = list_entry (ptr1, struct ebda_pci_rsrc, ebda_pci_rsrc_list); - debug ("%s - rsrc type: %x bus#: %x dev_func: %x start addr: %lx end addr: %lx\n", + debug ("%s - rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n", __FUNCTION__, ptr->rsrc_type ,ptr->bus_num, ptr->dev_fun,ptr->start_addr, ptr->end_addr); } } +static void __init print_ibm_slot (void) +{ + struct slot *ptr; + struct list_head *ptr1; + + list_for_each (ptr1, &ibmphp_slot_head) { + ptr = list_entry (ptr1, struct slot, ibm_slot_list); + debug ("%s - slot_number: %x \n", __FUNCTION__, ptr->number); + } +} + +static void __init print_opt_vg (void) +{ + struct opt_rio *ptr; + struct list_head *ptr1; + debug ("%s --- \n", __FUNCTION__); + list_for_each (ptr1, &opt_vg_head) { + ptr = list_entry (ptr1, struct opt_rio, opt_rio_list); + debug ("%s - rio_type %x \n", __FUNCTION__, ptr->rio_type); + debug ("%s - chassis_num: %x \n", __FUNCTION__, ptr->chassis_num); + debug ("%s - first_slot_num: %x \n", __FUNCTION__, ptr->first_slot_num); + debug ("%s - middle_num: %x \n", __FUNCTION__, ptr->middle_num); + } +} + static void __init print_ebda_hpc (void) { struct controller *hpc_ptr; @@ -221,6 +287,7 @@ static void __init print_ebda_hpc (void) break; case 2: + case 4: debug ("%s - wpegbbar: %lx\n", __FUNCTION__, hpc_ptr->u.wpeg_ctlr.wpegbbar); debug ("%s - i2c_addr: %x\n", __FUNCTION__, hpc_ptr->u.wpeg_ctlr.i2c_addr); debug ("%s - irq: %x\n", __FUNCTION__, hpc_ptr->irq); @@ -357,31 +424,382 @@ int __init ibmphp_access_ebda (void) rio_complete = 1; } + } - if (hs_complete && rio_complete) { - rc = ebda_rsrc_controller (); - if (rc) { - iounmap(io_mem); - return rc; - } - rc = ebda_rsrc_rsrc (); - if (rc) { - iounmap(io_mem); - return rc; - } + if (!hs_complete && !rio_complete) { + iounmap (io_mem); + return -ENODEV; + } + + if (rio_table_ptr) { + if (rio_complete == 1 && rio_table_ptr->ver_num == 3) { rc = ebda_rio_table (); if (rc) { - iounmap(io_mem); + iounmap (io_mem); return rc; - } - iounmap (io_mem); - return 0; + } } } + rc = ebda_rsrc_controller (); + if (rc) { + iounmap (io_mem); + return rc; + } + + rc = ebda_rsrc_rsrc (); + if (rc) { + iounmap (io_mem); + return rc; + } + iounmap (io_mem); - return -ENODEV; + return 0; } +/* + * map info of scalability details and rio details from physical address + */ +static int __init ebda_rio_table (void) +{ + u16 offset; + u8 i; + struct rio_detail *rio_detail_ptr; + + offset = rio_table_ptr->offset; + offset += 12 * rio_table_ptr->scal_count; + + // we do concern about rio details + for (i = 0; i < rio_table_ptr->riodev_count; i++) { + rio_detail_ptr = kmalloc (sizeof (struct rio_detail), GFP_KERNEL); + if (!rio_detail_ptr) + return -ENOMEM; + memset (rio_detail_ptr, 0, sizeof (struct rio_detail)); + rio_detail_ptr->rio_node_id = readb (io_mem + offset); + rio_detail_ptr->bbar = readl (io_mem + offset + 1); + rio_detail_ptr->rio_type = readb (io_mem + offset + 5); + rio_detail_ptr->owner_id = readb (io_mem + offset + 6); + rio_detail_ptr->port0_node_connect = readb (io_mem + offset + 7); + rio_detail_ptr->port0_port_connect = readb (io_mem + offset + 8); + rio_detail_ptr->port1_node_connect = readb (io_mem + offset + 9); + rio_detail_ptr->port1_port_connect = readb (io_mem + offset + 10); + rio_detail_ptr->first_slot_num = readb (io_mem + offset + 11); + rio_detail_ptr->status = readb (io_mem + offset + 12); + rio_detail_ptr->wpindex = readb (io_mem + offset + 13); + rio_detail_ptr->chassis_num = readb (io_mem + offset + 14); +// debug ("rio_node_id: %x\nbbar: %x\nrio_type: %x\nowner_id: %x\nport0_node: %x\nport0_port: %x\nport1_node: %x\nport1_port: %x\nfirst_slot_num: %x\nstatus: %x\n", rio_detail_ptr->rio_node_id, rio_detail_ptr->bbar, rio_detail_ptr->rio_type, rio_detail_ptr->owner_id, rio_detail_ptr->port0_node_connect, rio_detail_ptr->port0_port_connect, rio_detail_ptr->port1_node_connect, rio_detail_ptr->port1_port_connect, rio_detail_ptr->first_slot_num, rio_detail_ptr->status); + //create linked list of chassis + if (rio_detail_ptr->rio_type == 4 || rio_detail_ptr->rio_type == 5) + list_add (&rio_detail_ptr->rio_detail_list, &rio_vg_head); + //create linked list of expansion box + else if (rio_detail_ptr->rio_type == 6 || rio_detail_ptr->rio_type == 7) + list_add (&rio_detail_ptr->rio_detail_list, &rio_lo_head); + else + // not in my concern + kfree (rio_detail_ptr); + offset += 15; + } + print_lo_info (); + print_vg_info (); + return 0; +} + +/* + * reorganizing linked list of chassis + */ +static struct opt_rio *search_opt_vg (u8 chassis_num) +{ + struct opt_rio *ptr; + struct list_head *ptr1; + list_for_each (ptr1, &opt_vg_head) { + ptr = list_entry (ptr1, struct opt_rio, opt_rio_list); + if (ptr->chassis_num == chassis_num) + return ptr; + } + return NULL; +} + +static int __init combine_wpg_for_chassis (void) +{ + struct opt_rio *opt_rio_ptr = NULL; + struct rio_detail *rio_detail_ptr = NULL; + struct list_head *list_head_ptr = NULL; + + list_for_each (list_head_ptr, &rio_vg_head) { + rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list); + opt_rio_ptr = search_opt_vg (rio_detail_ptr->chassis_num); + if (!opt_rio_ptr) { + opt_rio_ptr = (struct opt_rio *) kmalloc (sizeof (struct opt_rio), GFP_KERNEL); + if (!opt_rio_ptr) + return -ENOMEM; + memset (opt_rio_ptr, 0, sizeof (struct opt_rio)); + opt_rio_ptr->rio_type = rio_detail_ptr->rio_type; + opt_rio_ptr->chassis_num = rio_detail_ptr->chassis_num; + opt_rio_ptr->first_slot_num = rio_detail_ptr->first_slot_num; + opt_rio_ptr->middle_num = rio_detail_ptr->first_slot_num; + list_add (&opt_rio_ptr->opt_rio_list, &opt_vg_head); + } else { + opt_rio_ptr->first_slot_num = min (opt_rio_ptr->first_slot_num, rio_detail_ptr->first_slot_num); + opt_rio_ptr->middle_num = max (opt_rio_ptr->middle_num, rio_detail_ptr->first_slot_num); + } + } + print_opt_vg (); + return 0; +} + +/* + * reorgnizing linked list of expansion box + */ +static struct opt_rio_lo *search_opt_lo (u8 chassis_num) +{ + struct opt_rio_lo *ptr; + struct list_head *ptr1; + list_for_each (ptr1, &opt_lo_head) { + ptr = list_entry (ptr1, struct opt_rio_lo, opt_rio_lo_list); + if (ptr->chassis_num == chassis_num) + return ptr; + } + return NULL; +} + +static int combine_wpg_for_expansion (void) +{ + struct opt_rio_lo *opt_rio_lo_ptr = NULL; + struct rio_detail *rio_detail_ptr = NULL; + struct list_head *list_head_ptr = NULL; + + list_for_each (list_head_ptr, &rio_lo_head) { + rio_detail_ptr = list_entry (list_head_ptr, struct rio_detail, rio_detail_list); + opt_rio_lo_ptr = search_opt_lo (rio_detail_ptr->chassis_num); + if (!opt_rio_lo_ptr) { + opt_rio_lo_ptr = (struct opt_rio_lo *) kmalloc (sizeof (struct opt_rio_lo), GFP_KERNEL); + if (!opt_rio_lo_ptr) + return -ENOMEM; + memset (opt_rio_lo_ptr, 0, sizeof (struct opt_rio_lo)); + opt_rio_lo_ptr->rio_type = rio_detail_ptr->rio_type; + opt_rio_lo_ptr->chassis_num = rio_detail_ptr->chassis_num; + opt_rio_lo_ptr->first_slot_num = rio_detail_ptr->first_slot_num; + opt_rio_lo_ptr->middle_num = rio_detail_ptr->first_slot_num; + opt_rio_lo_ptr->pack_count = 1; + + list_add (&opt_rio_lo_ptr->opt_rio_lo_list, &opt_lo_head); + } else { + opt_rio_lo_ptr->first_slot_num = min (opt_rio_lo_ptr->first_slot_num, rio_detail_ptr->first_slot_num); + opt_rio_lo_ptr->middle_num = max (opt_rio_lo_ptr->middle_num, rio_detail_ptr->first_slot_num); + opt_rio_lo_ptr->pack_count = 2; + } + } + return 0; +} + +static char *convert_2digits_to_char (int var) +{ + int bit; + char *str1; + + str = (char *) kmalloc (3, GFP_KERNEL); + memset (str, 0, 3); + str1 = (char *) kmalloc (2, GFP_KERNEL); + memset (str, 0, 3); + bit = (int)(var / 10); + switch (bit) { + case 0: + //one digit number + *str = (char)(var + 48); + return str; + default: + //2 digits number + *str1 = (char)(bit + 48); + strncpy (str, str1, 1); + memset (str1, 0, 3); + *str1 = (char)((var % 10) + 48); + strcat (str, str1); + return str; + } + return NULL; +} + +/* Since we don't know the max slot number per each chassis, hence go + * through the list of all chassis to find out the range + * Arguments: slot_num, 1st slot number of the chassis we think we are on, + * var (0 = chassis, 1 = expansion box) + */ +static int first_slot_num (u8 slot_num, u8 first_slot, u8 var) +{ + struct opt_rio *opt_vg_ptr = NULL; + struct opt_rio_lo *opt_lo_ptr = NULL; + struct list_head *ptr = NULL; + int rc = 0; + + if (!var) { + list_for_each (ptr, &opt_vg_head) { + opt_vg_ptr = list_entry (ptr, struct opt_rio, opt_rio_list); + if ((first_slot < opt_vg_ptr->first_slot_num) && (slot_num >= opt_vg_ptr->first_slot_num)) { + rc = -ENODEV; + break; + } + } + } else { + list_for_each (ptr, &opt_lo_head) { + opt_lo_ptr = list_entry (ptr, struct opt_rio_lo, opt_rio_lo_list); + if ((first_slot < opt_lo_ptr->first_slot_num) && (slot_num >= opt_lo_ptr->first_slot_num)) { + rc = -ENODEV; + break; + } + } + } + return rc; +} + +static struct opt_rio_lo * find_rxe_num (u8 slot_num) +{ + struct opt_rio_lo *opt_lo_ptr; + struct list_head *ptr; + + list_for_each (ptr, &opt_lo_head) { + opt_lo_ptr = list_entry (ptr, struct opt_rio_lo, opt_rio_lo_list); + //check to see if this slot_num belongs to expansion box + if ((slot_num >= opt_lo_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_lo_ptr->first_slot_num, 1))) + return opt_lo_ptr; + } + return NULL; +} + +static struct opt_rio * find_chassis_num (u8 slot_num) +{ + struct opt_rio *opt_vg_ptr; + struct list_head *ptr; + + list_for_each (ptr, &opt_vg_head) { + opt_vg_ptr = list_entry (ptr, struct opt_rio, opt_rio_list); + //check to see if this slot_num belongs to chassis + if ((slot_num >= opt_vg_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_vg_ptr->first_slot_num, 0))) + return opt_vg_ptr; + } + return NULL; +} + +/* This routine will find out how many slots are in the chassis, so that + * the slot numbers for rxe100 would start from 1, and not from 7, or 6 etc + */ +static u8 calculate_first_slot (u8 slot_num) +{ + u8 first_slot = 1; + struct list_head * list; + struct slot * slot_cur; + + list_for_each (list, &ibmphp_slot_head) { + slot_cur = list_entry (list, struct slot, ibm_slot_list); + if (slot_cur->ctrl) { + if ((slot_cur->ctrl->ctlr_type != 4) && (slot_cur->ctrl->ending_slot_num > first_slot) && (slot_num > slot_cur->ctrl->ending_slot_num)) + first_slot = slot_cur->ctrl->ending_slot_num; + } + } + return first_slot + 1; + +} +static char *create_file_name (struct slot * slot_cur) +{ + struct opt_rio *opt_vg_ptr = NULL; + struct opt_rio_lo *opt_lo_ptr = NULL; + char *ptr_chassis_num, *ptr_rxe_num, *ptr_slot_num; + int which = 0; /* rxe = 1, chassis = 0 */ + u8 number = 1; /* either chassis or rxe # */ + u8 first_slot = 1; + u8 slot_num; + u8 flag = 0; + + if (!slot_cur) { + err ("Structure passed is empty \n"); + return NULL; + } + + slot_num = slot_cur->number; + + chassis_str = (char *) kmalloc (30, GFP_KERNEL); + memset (chassis_str, 0, 30); + rxe_str = (char *) kmalloc (30, GFP_KERNEL); + memset (rxe_str, 0, 30); + ptr_chassis_num = (char *) kmalloc (3, GFP_KERNEL); + memset (ptr_chassis_num, 0, 3); + ptr_rxe_num = (char *) kmalloc (3, GFP_KERNEL); + memset (ptr_rxe_num, 0, 3); + ptr_slot_num = (char *) kmalloc (3, GFP_KERNEL); + memset (ptr_slot_num, 0, 3); + + strcpy (chassis_str, "chassis"); + strcpy (rxe_str, "rxe"); + + if (rio_table_ptr) { + if (rio_table_ptr->ver_num == 3) { + opt_vg_ptr = find_chassis_num (slot_num); + opt_lo_ptr = find_rxe_num (slot_num); + } + } + if (opt_vg_ptr) { + if (opt_lo_ptr) { + if ((slot_num - opt_vg_ptr->first_slot_num) > (slot_num - opt_lo_ptr->first_slot_num)) { + number = opt_lo_ptr->chassis_num; + first_slot = opt_lo_ptr->first_slot_num; + which = 1; /* it is RXE */ + } else { + first_slot = opt_vg_ptr->first_slot_num; + number = opt_vg_ptr->chassis_num; + which = 0; + } + } else { + first_slot = opt_vg_ptr->first_slot_num; + number = opt_vg_ptr->chassis_num; + which = 0; + } + ++flag; + } else if (opt_lo_ptr) { + number = opt_lo_ptr->chassis_num; + first_slot = opt_lo_ptr->first_slot_num; + which = 1; + ++flag; + } else if (rio_table_ptr) { + if (rio_table_ptr->ver_num == 3) { + /* if both NULL and we DO have correct RIO table in BIOS */ + return NULL; + } + } + if (!flag) { + if (slot_cur->ctrl->ctlr_type == 4) { + first_slot = calculate_first_slot (slot_num); + which = 1; + } else { + which = 0; + } + } + + switch (which) { + case 0: + /* Chassis */ + *ptr_chassis_num = (char)(number + 48); + strcat (chassis_str, ptr_chassis_num); + kfree (ptr_chassis_num); + strcat (chassis_str, "slot"); + ptr_slot_num = convert_2digits_to_char (slot_num - first_slot + 1); + strcat (chassis_str, ptr_slot_num); + kfree (ptr_slot_num); + return chassis_str; + break; + case 1: + /* RXE */ + *ptr_rxe_num = (char)(number + 48); + strcat (rxe_str, ptr_rxe_num); + kfree (ptr_rxe_num); + strcat (rxe_str, "slot"); + ptr_slot_num = convert_2digits_to_char (slot_num - first_slot + 1); + strcat (rxe_str, ptr_slot_num); + kfree (ptr_slot_num); + return rxe_str; + break; + } + return NULL; +} + +static struct pci_driver ibmphp_driver; /* * map info (ctlr-id, slot count, slot#.. bus count, bus#, ctlr type...) of @@ -400,6 +818,9 @@ static int __init ebda_rsrc_controller (void) struct ebda_hpc_slot *slot_ptr; struct bus_info *bus_info_ptr1, *bus_info_ptr2; int rc; + int retval; + struct slot *slot_cur; + struct list_head *list; addr = hpc_list_ptr->phys_addr; for (ctlr = 0; ctlr < hpc_list_ptr->num_ctlrs; ctlr++) { @@ -510,23 +931,22 @@ static int __init ebda_rsrc_controller (void) hpc_ptr->u.pci_ctlr.bus = readb (io_mem + addr); hpc_ptr->u.pci_ctlr.dev_fun = readb (io_mem + addr + 1); hpc_ptr->irq = readb (io_mem + addr + 2); - addr += 3; + addr += 3; + debug ("ctrl bus = %x, ctlr devfun = %x, irq = %x\n", hpc_ptr->u.pci_ctlr.bus, hpc_ptr->u.pci_ctlr.dev_fun, hpc_ptr->irq); break; case 0: hpc_ptr->u.isa_ctlr.io_start = readw (io_mem + addr); hpc_ptr->u.isa_ctlr.io_end = readw (io_mem + addr + 2); + retval = check_region (hpc_ptr->u.isa_ctlr.io_start, (hpc_ptr->u.isa_ctlr.io_end - hpc_ptr->u.isa_ctlr.io_start + 1)); + if (retval) + return -ENODEV; + request_region (hpc_ptr->u.isa_ctlr.io_start, (hpc_ptr->u.isa_ctlr.io_end - hpc_ptr->u.isa_ctlr.io_start + 1), "ibmphp"); hpc_ptr->irq = readb (io_mem + addr + 4); addr += 5; break; case 2: - hpc_ptr->u.wpeg_ctlr.wpegbbar = readl (io_mem + addr); - hpc_ptr->u.wpeg_ctlr.i2c_addr = readb (io_mem + addr + 4); - - hpc_ptr->irq = readb (io_mem + addr + 5); - addr += 6; - break; case 4: hpc_ptr->u.wpeg_ctlr.wpegbbar = readl (io_mem + addr); hpc_ptr->u.wpeg_ctlr.i2c_addr = readb (io_mem + addr + 4); @@ -537,12 +957,10 @@ static int __init ebda_rsrc_controller (void) iounmap (io_mem); return -ENODEV; } - /* following 3 line: Now our driver only supports I2c ctlrType */ - if ((hpc_ptr->ctlr_type != 2) && (hpc_ptr->ctlr_type != 4)) { - err ("Please run this driver on ibm xseries440\n "); - return -ENODEV; - } + //reorganize chassis' linked list + combine_wpg_for_chassis (); + combine_wpg_for_expansion (); hpc_ptr->revision = 0xff; hpc_ptr->options = 0xff; hpc_ptr->starting_slot_num = hpc_ptr->slots[0].slot_num; @@ -566,7 +984,7 @@ static int __init ebda_rsrc_controller (void) } memset (hp_slot_ptr->info, 0, sizeof (struct hotplug_slot_info)); - hp_slot_ptr->name = (char *) kmalloc (10, GFP_KERNEL); + hp_slot_ptr->name = (char *) kmalloc (30, GFP_KERNEL); if (!hp_slot_ptr->name) { iounmap (io_mem); kfree (hp_slot_ptr->info); @@ -583,9 +1001,7 @@ static int __init ebda_rsrc_controller (void) return -ENOMEM; } - ((struct slot *)hp_slot_ptr->private)->flag = TRUE; - snprintf (hp_slot_ptr->name, 10, "%d", hpc_ptr->slots[index].slot_num); ((struct slot *) hp_slot_ptr->private)->capabilities = hpc_ptr->slots[index].slot_cap; if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_133_MAX) == EBDA_SLOT_133_MAX) @@ -617,7 +1033,6 @@ static int __init ebda_rsrc_controller (void) ((struct slot *) hp_slot_ptr->private)->number = hpc_ptr->slots[index].slot_num; ((struct slot *) hp_slot_ptr->private)->hotplug_slot = hp_slot_ptr; - rc = ibmphp_hpc_fillhpslotinfo (hp_slot_ptr); if (rc) { iounmap (io_mem); @@ -631,8 +1046,6 @@ static int __init ebda_rsrc_controller (void) } hp_slot_ptr->ops = &ibmphp_hotplug_slot_ops; - pci_hp_register (hp_slot_ptr); - // end of registering ibm slot with hotplug core list_add (& ((struct slot *)(hp_slot_ptr->private))->ibm_slot_list, &ibmphp_slot_head); @@ -642,7 +1055,20 @@ static int __init ebda_rsrc_controller (void) list_add (&hpc_ptr->ebda_hpc_list, &ebda_hpc_head ); } /* each hpc */ + + list_for_each (list, &ibmphp_slot_head) { + slot_cur = list_entry (list, struct slot, ibm_slot_list); + + snprintf (slot_cur->hotplug_slot->name, 30, "%s", create_file_name (slot_cur)); + if (chassis_str) + kfree (chassis_str); + if (rxe_str) + kfree (rxe_str); + pci_hp_register (slot_cur->hotplug_slot); + } + print_ebda_hpc (); + print_ibm_slot (); return 0; } @@ -682,7 +1108,7 @@ static int __init ebda_rsrc_rsrc (void) addr += 6; debug ("rsrc from io type ----\n"); - debug ("rsrc type: %x bus#: %x dev_func: %x start addr: %lx end addr: %lx\n", + debug ("rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n", rsrc_ptr->rsrc_type, rsrc_ptr->bus_num, rsrc_ptr->dev_fun, rsrc_ptr->start_addr, rsrc_ptr->end_addr); list_add (&rsrc_ptr->ebda_pci_rsrc_list, &ibmphp_ebda_pci_rsrc_head); @@ -703,7 +1129,7 @@ static int __init ebda_rsrc_rsrc (void) addr += 10; debug ("rsrc from mem or pfm ---\n"); - debug ("rsrc type: %x bus#: %x dev_func: %x start addr: %lx end addr: %lx\n", + debug ("rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n", rsrc_ptr->rsrc_type, rsrc_ptr->bus_num, rsrc_ptr->dev_fun, rsrc_ptr->start_addr, rsrc_ptr->end_addr); list_add (&rsrc_ptr->ebda_pci_rsrc_list, &ibmphp_ebda_pci_rsrc_head); @@ -715,56 +1141,6 @@ static int __init ebda_rsrc_rsrc (void) return 0; } -/* - * map info of scalability details and rio details from physical address - */ -static int __init ebda_rio_table(void) -{ - u16 offset; - u8 i; - struct scal_detail *scal_detail_ptr; - struct rio_detail *rio_detail_ptr; - - offset = rio_table_ptr->offset; - for (i = 0; i < rio_table_ptr->scal_count; i++) { - - scal_detail_ptr = kmalloc (sizeof (struct scal_detail), GFP_KERNEL ); - if (!scal_detail_ptr ) - return -ENOMEM; - memset (scal_detail_ptr, 0, sizeof (struct scal_detail) ); - scal_detail_ptr->node_id = readb (io_mem + offset); - scal_detail_ptr->cbar = readl (io_mem+ offset + 1); - scal_detail_ptr->port0_node_connect = readb (io_mem + 5); - scal_detail_ptr->port0_port_connect = readb (io_mem + 6); - scal_detail_ptr->port1_node_connect = readb (io_mem + 7); - scal_detail_ptr->port1_port_connect = readb (io_mem + 8); - scal_detail_ptr->port2_node_connect = readb (io_mem + 9); - scal_detail_ptr->port2_port_connect = readb (io_mem + 10); - debug ("node_id: %x\ncbar: %x\nport0_node: %x\nport0_port: %x\nport1_node: %x\nport1_port: %x\nport2_node: %x\nport2_port: %x\n", scal_detail_ptr->node_id, scal_detail_ptr->cbar, scal_detail_ptr->port0_node_connect, scal_detail_ptr->port0_port_connect, scal_detail_ptr->port1_node_connect, scal_detail_ptr->port1_port_connect, scal_detail_ptr->port2_node_connect, scal_detail_ptr->port2_port_connect); -// list_add (&scal_detail_ptr->scal_detail_list, &scal_detail_head); - offset += 11; - } - for (i=0; i < rio_table_ptr->riodev_count; i++) { - rio_detail_ptr = kmalloc (sizeof (struct rio_detail), GFP_KERNEL ); - if (!rio_detail_ptr ) - return -ENOMEM; - memset (rio_detail_ptr, 0, sizeof (struct rio_detail) ); - rio_detail_ptr->rio_node_id = readb (io_mem + offset ); - rio_detail_ptr->bbar = readl (io_mem + offset + 1); - rio_detail_ptr->rio_type = readb (io_mem + offset + 5); - rio_detail_ptr->owner_id = readb (io_mem + offset + 6); - rio_detail_ptr->port0_node_connect = readb (io_mem + offset + 7); - rio_detail_ptr->port0_port_connect = readb (io_mem + offset + 8); - rio_detail_ptr->port1_node_connect = readb (io_mem + offset + 9); - rio_detail_ptr->port1_port_connect = readb (io_mem + offset + 10); - rio_detail_ptr->first_slot_num = readb (io_mem + offset + 11); - rio_detail_ptr->status = readb (io_mem + offset + 12); - debug ("rio_node_id: %x\nbbar: %x\nrio_type: %x\nowner_id: %x\nport0_node: %x\nport0_port: %x\nport1_node: %x\nport1_port: %x\nfirst_slot_num: %x\nstatus: %x\n", rio_detail_ptr->rio_node_id, rio_detail_ptr->bbar, rio_detail_ptr->rio_type, rio_detail_ptr->owner_id, rio_detail_ptr->port0_node_connect, rio_detail_ptr->port0_port_connect, rio_detail_ptr->port1_node_connect, rio_detail_ptr->port1_port_connect, rio_detail_ptr->first_slot_num, rio_detail_ptr->status); - offset += 13; - } - return 0; -} - u16 ibmphp_get_total_controllers (void) { return hpc_list_ptr->num_ctlrs; @@ -830,32 +1206,21 @@ void ibmphp_free_bus_info_queue (void) } } -/* - * Calculate the total hot pluggable slots controlled by total hpcs - */ -/* -int ibmphp_get_total_hp_slots (void) -{ - struct ebda_hpc *ptr; - int slot_num = 0; - - ptr = ebda_hpc_head; - while (ptr != NULL) { - slot_num += ptr->slot_count; - ptr = ptr->next; - } - return slot_num; -} -*/ - void ibmphp_free_ebda_hpc_queue (void) { - struct controller *controller; + struct controller *controller = NULL; struct list_head *list; struct list_head *next; + int pci_flag = 0; list_for_each_safe (list, next, &ebda_hpc_head) { controller = list_entry (list, struct controller, ebda_hpc_list); + if (controller->ctlr_type == 0) + release_region (controller->u.isa_ctlr.io_start, (controller->u.isa_ctlr.io_end - controller->u.isa_ctlr.io_start + 1)); + else if ((controller->ctlr_type == 1) && (!pci_flag)) { + ++pci_flag; + pci_unregister_driver (&ibmphp_driver); + } free_ebda_hpc (controller); } } @@ -873,3 +1238,58 @@ void ibmphp_free_ebda_pci_rsrc_queue (void) } } +static struct pci_device_id id_table[] __devinitdata = { + { + vendor: PCI_VENDOR_ID_IBM, + device: HPC_DEVICE_ID, + subvendor: PCI_VENDOR_ID_IBM, + subdevice: HPC_SUBSYSTEM_ID, + class: ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00), + }, {} +}; + +MODULE_DEVICE_TABLE(pci, id_table); + +static int ibmphp_probe (struct pci_dev *, const struct pci_device_id *); +static struct pci_driver ibmphp_driver = { + name: "ibmphp", + id_table: id_table, + probe: ibmphp_probe, +}; + +int ibmphp_register_pci (void) +{ + struct controller *ctrl; + struct list_head *tmp; + int rc = 0; + + list_for_each (tmp, &ebda_hpc_head) { + ctrl = list_entry (tmp, struct controller, ebda_hpc_list); + if (ctrl->ctlr_type == 1) { + rc = pci_module_init (&ibmphp_driver); + break; + } + } + return rc; +} +static int ibmphp_probe (struct pci_dev * dev, const struct pci_device_id *ids) +{ + struct controller *ctrl; + struct list_head *tmp; + + debug ("inside ibmphp_probe \n"); + + list_for_each (tmp, &ebda_hpc_head) { + ctrl = list_entry (tmp, struct controller, ebda_hpc_list); + if (ctrl->ctlr_type == 1) { + if ((dev->devfn == ctrl->u.pci_ctlr.dev_fun) && (dev->bus->number == ctrl->u.pci_ctlr.bus)) { + ctrl->ctrl_dev = dev; + debug ("found device!!! \n"); + debug ("dev->device = %x, dev->subsystem_device = %x\n", dev->device, dev->subsystem_device); + return 0; + } + } + } + return -ENODEV; +} + diff --git a/drivers/hotplug/ibmphp_hpc.c b/drivers/hotplug/ibmphp_hpc.c index bf2e067aaad0..ae959809e8a8 100644 --- a/drivers/hotplug/ibmphp_hpc.c +++ b/drivers/hotplug/ibmphp_hpc.c @@ -107,8 +107,8 @@ static struct semaphore sem_exit; // make sure polling thread goes away //---------------------------------------------------------------------------- // local function prototypes //---------------------------------------------------------------------------- -static u8 ctrl_read (struct controller *, void *, u8); -static u8 ctrl_write (struct controller *, void *, u8, u8); +static u8 i2c_ctrl_read (struct controller *, void *, u8); +static u8 i2c_ctrl_write (struct controller *, void *, u8, u8); static u8 hpc_writecmdtoindex (u8, u8); static u8 hpc_readcmdtoindex (u8, u8); static void get_hpc_access (void); @@ -142,12 +142,12 @@ void __init ibmphp_hpc_initvars (void) } /*---------------------------------------------------------------------- -* Name: ctrl_read +* Name: i2c_ctrl_read * * Action: read from HPC over I2C * *---------------------------------------------------------------------*/ -static u8 ctrl_read (struct controller *ctlr_ptr, void *WPGBbar, u8 index) +static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void *WPGBbar, u8 index) { u8 status; int i; @@ -249,13 +249,13 @@ static u8 ctrl_read (struct controller *ctlr_ptr, void *WPGBbar, u8 index) } /*---------------------------------------------------------------------- -* Name: ctrl_write +* Name: i2c_ctrl_write * * Action: write to HPC over I2C * * Return 0 or error codes *---------------------------------------------------------------------*/ -static u8 ctrl_write (struct controller *ctlr_ptr, void *WPGBbar, u8 index, u8 cmd) +static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void *WPGBbar, u8 index, u8 cmd) { u8 rc; void *wpg_addr; // base addr + offset @@ -351,6 +351,93 @@ static u8 ctrl_write (struct controller *ctlr_ptr, void *WPGBbar, u8 index, u8 c return (rc); } +//------------------------------------------------------------ +// Read from ISA type HPC +//------------------------------------------------------------ +static u8 isa_ctrl_read (struct controller *ctlr_ptr, u8 offset) +{ + u16 start_address; + u16 end_address; + u8 data; + + start_address = ctlr_ptr->u.isa_ctlr.io_start; + end_address = ctlr_ptr->u.isa_ctlr.io_end; + data = inb (start_address + offset); + return data; +} + +//-------------------------------------------------------------- +// Write to ISA type HPC +//-------------------------------------------------------------- +static void isa_ctrl_write (struct controller *ctlr_ptr, u8 offset, u8 data) +{ + u16 start_address; + u16 port_address; + + start_address = ctlr_ptr->u.isa_ctlr.io_start; + port_address = start_address + (u16) offset; + outb (data, port_address); +} + +static u8 pci_ctrl_read (struct controller *ctrl, u8 offset) +{ + u8 data = 0x00; + debug ("inside pci_ctrl_read\n"); + if (ctrl->ctrl_dev) + pci_read_config_byte (ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, &data); + return data; +} + +static u8 pci_ctrl_write (struct controller *ctrl, u8 offset, u8 data) +{ + u8 rc = -ENODEV; + debug ("inside pci_ctrl_write\n"); + if (ctrl->ctrl_dev) { + pci_write_config_byte (ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, data); + rc = 0; + } + return rc; +} + +static u8 ctrl_read (struct controller *ctlr, void *base, u8 offset) +{ + u8 rc; + switch (ctlr->ctlr_type) { + case 0: + rc = isa_ctrl_read (ctlr, offset); + break; + case 1: + rc = pci_ctrl_read (ctlr, offset); + break; + case 2: + case 4: + rc = i2c_ctrl_read (ctlr, base, offset); + break; + default: + return -ENODEV; + } + return rc; +} + +static u8 ctrl_write (struct controller *ctlr, void *base, u8 offset, u8 data) +{ + u8 rc = 0; + switch (ctlr->ctlr_type) { + case 0: + isa_ctrl_write(ctlr, offset, data); + break; + case 1: + rc = pci_ctrl_write (ctlr, offset, data); + break; + case 2: + case 4: + rc = i2c_ctrl_write(ctlr, base, offset, data); + break; + default: + return -ENODEV; + } + return rc; +} /*---------------------------------------------------------------------- * Name: hpc_writecmdtoindex() * @@ -449,7 +536,7 @@ static u8 hpc_readcmdtoindex (u8 cmd, u8 index) *---------------------------------------------------------------------*/ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus) { - void *wpg_bbar; + void *wpg_bbar = NULL; struct controller *ctlr_ptr; struct list_head *pslotlist; u8 index, status; @@ -491,7 +578,8 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus) //-------------------------------------------------------------------- // map physical address to logical address //-------------------------------------------------------------------- - wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE); + if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) + wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE); //-------------------------------------------------------------------- // check controller status before reading @@ -569,7 +657,11 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus) //-------------------------------------------------------------------- // cleanup //-------------------------------------------------------------------- - iounmap (wpg_bbar); // remove physical to logical address mapping + + // remove physical to logical address mapping + if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) + iounmap (wpg_bbar); + free_hpc_access (); debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc); @@ -583,7 +675,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus) *---------------------------------------------------------------------*/ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) { - void *wpg_bbar; + void *wpg_bbar = NULL; struct controller *ctlr_ptr; u8 index, status; int busindex; @@ -626,12 +718,13 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) //-------------------------------------------------------------------- // map physical address to logical address //-------------------------------------------------------------------- - wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE); + if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) { + wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE); - debug ("%s - ctlr id[%x] physical[%lx] logical[%lx] i2c[%x]\n", __FUNCTION__, + debug ("%s - ctlr id[%x] physical[%lx] logical[%lx] i2c[%x]\n", __FUNCTION__, ctlr_ptr->ctlr_id, (ulong) (ctlr_ptr->u.wpeg_ctlr.wpegbbar), (ulong) wpg_bbar, ctlr_ptr->u.wpeg_ctlr.i2c_addr); - + } //-------------------------------------------------------------------- // check controller status before writing //-------------------------------------------------------------------- @@ -668,7 +761,10 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) ctlr_ptr->status = status; } // cleanup - iounmap (wpg_bbar); // remove physical to logical address mapping + + // remove physical to logical address mapping + if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) + iounmap (wpg_bbar); free_hpc_access (); debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc); @@ -701,6 +797,7 @@ void free_hpc_access (void) void ibmphp_lock_operations (void) { down (&semOperations); + to_debug = TRUE; } /*---------------------------------------------------------------------- @@ -710,6 +807,7 @@ void ibmphp_unlock_operations (void) { debug ("%s - Entry\n", __FUNCTION__); up (&semOperations); + to_debug = FALSE; debug ("%s - Exit\n", __FUNCTION__); } @@ -734,82 +832,86 @@ static void poll_hpc (void) debug ("%s - Entry\n", __FUNCTION__); while (!ibmphp_shutdown) { + if (ibmphp_shutdown) + break; + /* try to get the lock to do some kind of harware access */ down (&semOperations); switch (poll_state) { - case POLL_LATCH_REGISTER: - oldlatchlow = curlatchlow; - ctrl_count = 0x00; - list_for_each (pslotlist, &ibmphp_slot_head) { - if (ctrl_count >= ibmphp_get_total_controllers()) - break; - pslot = list_entry (pslotlist, struct slot, ibm_slot_list); - if (pslot->ctrl->ctlr_relative_id == ctrl_count) { - ctrl_count++; - if (READ_SLOT_LATCH (pslot->ctrl)) { - rc = ibmphp_hpc_readslot (pslot, - READ_SLOTLATCHLOWREG, - &curlatchlow); - if (oldlatchlow != curlatchlow) - process_changeinlatch (oldlatchlow, - curlatchlow, - pslot->ctrl); - } + case POLL_LATCH_REGISTER: + oldlatchlow = curlatchlow; + ctrl_count = 0x00; + list_for_each (pslotlist, &ibmphp_slot_head) { + if (ctrl_count >= ibmphp_get_total_controllers()) + break; + pslot = list_entry (pslotlist, struct slot, ibm_slot_list); + if (pslot->ctrl->ctlr_relative_id == ctrl_count) { + ctrl_count++; + if (READ_SLOT_LATCH (pslot->ctrl)) { + rc = ibmphp_hpc_readslot (pslot, + READ_SLOTLATCHLOWREG, + &curlatchlow); + if (oldlatchlow != curlatchlow) + process_changeinlatch (oldlatchlow, + curlatchlow, + pslot->ctrl); } } - poll_state = POLL_SLOTS; - break; - - case POLL_SLOTS: - list_for_each (pslotlist, &ibmphp_slot_head) { - pslot = list_entry (pslotlist, struct slot, ibm_slot_list); - // make a copy of the old status - memcpy ((void *) &myslot, (void *) pslot, - sizeof (struct slot)); - rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL); - if ((myslot.status != pslot->status) - || (myslot.ext_status != pslot->ext_status)) - process_changeinstatus (pslot, &myslot); + } + ++poll_count; + poll_state = POLL_SLEEP; + break; + case POLL_SLOTS: + list_for_each (pslotlist, &ibmphp_slot_head) { + pslot = list_entry (pslotlist, struct slot, ibm_slot_list); + // make a copy of the old status + memcpy ((void *) &myslot, (void *) pslot, + sizeof (struct slot)); + rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL); + if ((myslot.status != pslot->status) + || (myslot.ext_status != pslot->ext_status)) + process_changeinstatus (pslot, &myslot); + } + ctrl_count = 0x00; + list_for_each (pslotlist, &ibmphp_slot_head) { + if (ctrl_count >= ibmphp_get_total_controllers()) + break; + pslot = list_entry (pslotlist, struct slot, ibm_slot_list); + if (pslot->ctrl->ctlr_relative_id == ctrl_count) { + ctrl_count++; + if (READ_SLOT_LATCH (pslot->ctrl)) + rc = ibmphp_hpc_readslot (pslot, + READ_SLOTLATCHLOWREG, + &curlatchlow); } + } + ++poll_count; + poll_state = POLL_SLEEP; + break; + case POLL_SLEEP: + /* don't sleep with a lock on the hardware */ + up (&semOperations); + long_delay (POLL_INTERVAL_SEC * HZ); - ctrl_count = 0x00; - list_for_each (pslotlist, &ibmphp_slot_head) { - if (ctrl_count >= ibmphp_get_total_controllers()) - break; - pslot = list_entry (pslotlist, struct slot, ibm_slot_list); - if (pslot->ctrl->ctlr_relative_id == ctrl_count) { - ctrl_count++; - if (READ_SLOT_LATCH (pslot->ctrl)) - rc = ibmphp_hpc_readslot (pslot, - READ_SLOTLATCHLOWREG, - &curlatchlow); - } - } - ++poll_count; - if (poll_count >= POLL_LATCH_CNT) { - poll_count = 0; - poll_state = POLL_SLEEP; - } + if (ibmphp_shutdown) break; - - case POLL_SLEEP: - /* don't sleep with a lock on the hardware */ - up (&semOperations); - long_delay (POLL_INTERVAL_SEC * HZ); - down (&semOperations); + + down (&semOperations); + + if (poll_count >= POLL_LATCH_CNT) { + poll_count = 0; + poll_state = POLL_SLOTS; + } else poll_state = POLL_LATCH_REGISTER; - break; - } - + break; + } /* give up the harware semaphore */ up (&semOperations); - /* sleep for a short time just for good measure */ set_current_state (TASK_INTERRUPTIBLE); schedule_timeout (HZ/10); } - up (&sem_exit); debug ("%s - Exit\n", __FUNCTION__); } @@ -1070,15 +1172,23 @@ void __exit ibmphp_hpc_stop_poll_thread (void) debug ("%s - Entry\n", __FUNCTION__); ibmphp_shutdown = TRUE; + debug ("before locking operations \n"); ibmphp_lock_operations (); - + debug ("after locking operations \n"); + // wait for poll thread to exit + debug ("before sem_exit down \n"); down (&sem_exit); + debug ("after sem_exit down \n"); // cleanup + debug ("before free_hpc_access \n"); free_hpc_access (); + debug ("after free_hpc_access \n"); ibmphp_unlock_operations (); + debug ("after unlock operations \n"); up (&sem_exit); + debug ("after sem exit up\n"); debug ("%s - Exit\n", __FUNCTION__); } diff --git a/drivers/hotplug/ibmphp_pci.c b/drivers/hotplug/ibmphp_pci.c index 6273c448880f..cfc9ecffd650 100644 --- a/drivers/hotplug/ibmphp_pci.c +++ b/drivers/hotplug/ibmphp_pci.c @@ -104,11 +104,15 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) /* For every function on the card */ for (function = 0x00; function < 0x08; function++) { + unsigned int devfn = PCI_DEVFN(device, function); + ibmphp_pci_bus->number = cur_func->busno; + cur_func->function = function; - debug ("inside the loop, cur_func->busno = %x, cur_func->device = %x, cur_func->funcion = %x\n", cur_func->busno, device, function); + debug ("inside the loop, cur_func->busno = %x, cur_func->device = %x, cur_func->funcion = %x\n", + cur_func->busno, cur_func->device, cur_func->function); - pci_read_config_word_nodev (ibmphp_pci_root_ops, cur_func->busno, device, function, PCI_VENDOR_ID, &vendor_id); + pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id); debug ("vendor_id is %x\n", vendor_id); if (vendor_id != PCI_VENDOR_ID_NOTVALID) { @@ -122,8 +126,8 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) * |_=> 0 = single function device, 1 = multi-function device */ - pci_read_config_byte_nodev (ibmphp_pci_root_ops, cur_func->busno, device, function, PCI_HEADER_TYPE, &hdr_type); - pci_read_config_dword_nodev (ibmphp_pci_root_ops, cur_func->busno, device, function, PCI_CLASS_REVISION, &class); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type); + pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class); class_code = class >> 24; debug ("hrd_type = %x, class = %x, class_code %x \n", hdr_type, class, class_code); @@ -195,7 +199,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) goto error; } - pci_read_config_byte_nodev (ibmphp_pci_root_ops, cur_func->busno, device, function, PCI_SECONDARY_BUS, &sec_number); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); flag = FALSE; for (i = 0; i < 32; i++) { if (func->devices[i]) { @@ -267,8 +271,9 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno) cleanup_count = 2; goto error; } - debug ("cur_func->busno = %x, device = %x, function = %x\n", cur_func->busno, device, function); - pci_read_config_byte_nodev (ibmphp_pci_root_ops, cur_func->busno, device, function, PCI_SECONDARY_BUS, &sec_number); + debug ("cur_func->busno = %x, device = %x, function = %x\n", + cur_func->busno, device, function); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); debug ("after configuring bridge..., sec_number = %x\n", sec_number); flag = FALSE; for (i = 0; i < 32; i++) { @@ -361,13 +366,12 @@ static int configure_device (struct pci_func *func) struct resource_node *mem[6]; struct resource_node *mem_tmp; struct resource_node *pfmem[6]; - u8 device; - u8 function; + unsigned int devfn; debug ("%s - inside\n", __FUNCTION__); - device = func->device; - function = func->function; + devfn = PCI_DEVFN(func->device, func->function); + ibmphp_pci_bus->number = func->busno; for (count = 0; address[count]; count++) { /* for 6 BARs */ @@ -384,8 +388,8 @@ static int configure_device (struct pci_func *func) pcibios_write_config_dword(cur_func->busno, cur_func->device, PCI_BASE_ADDRESS_0 + 4 * count, 0xFFFFFFFF); */ - pci_write_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], 0xFFFFFFFF); - pci_read_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], &bar[count]); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF); + pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]); if (!bar[count]) /* This BAR is not implemented */ continue; @@ -421,11 +425,11 @@ static int configure_device (struct pci_func *func) kfree (io[count]); return -EIO; } - pci_write_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], func->io[count]->start); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->io[count]->start); /* _______________This is for debugging purposes only_____________________ */ debug ("b4 writing, the IO address is %x\n", func->io[count]->start); - pci_read_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], &bar[count]); + pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]); debug ("after writing.... the start address is %x\n", bar[count]); /* _________________________________________________________________________*/ @@ -484,11 +488,11 @@ static int configure_device (struct pci_func *func) } } - pci_write_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], func->pfmem[count]->start); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->pfmem[count]->start); - /*_______________This if for debugging purposes only______________________________*/ + /*_______________This is for debugging purposes only______________________________*/ debug ("b4 writing, start addres is %x\n", func->pfmem[count]->start); - pci_read_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], &bar[count]); + pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]); debug ("after writing, start address is %x\n", bar[count]); /*_________________________________________________________________________________*/ @@ -496,7 +500,7 @@ static int configure_device (struct pci_func *func) debug ("inside the mem 64 case, count %d\n", count); count += 1; /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */ - pci_write_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], 0x00000000); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000); } } else { /* regular memory */ @@ -526,10 +530,10 @@ static int configure_device (struct pci_func *func) kfree (mem[count]); return -EIO; } - pci_write_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], func->mem[count]->start); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->mem[count]->start); /* _______________________This is for debugging purposes only _______________________*/ debug ("b4 writing, start address is %x\n", func->mem[count]->start); - pci_read_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], &bar[count]); + pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]); debug ("after writing, the address is %x\n", bar[count]); /* __________________________________________________________________________________*/ @@ -538,22 +542,22 @@ static int configure_device (struct pci_func *func) debug ("inside mem 64 case, reg. mem, count %d\n", count); count += 1; /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */ - pci_write_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], 0x00000000); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000); } } } /* end of mem */ } /* end of for */ func->bus = 0; /* To indicate that this is not a PPB */ - pci_read_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_INTERRUPT_PIN, &irq); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_PIN, &irq); if ((irq > 0x00) && (irq < 0x05)) - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_INTERRUPT_LINE, func->irq[irq - 1]); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_LINE, func->irq[irq - 1]); - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_CACHE_LINE_SIZE, CACHE); - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_LATENCY_TIMER, LATENCY); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY); - pci_write_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_ROM_ADDRESS, 0x00L); - pci_write_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_COMMAND, DEVICEENABLE); + pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L); + pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE); return 0; } @@ -593,24 +597,23 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) 0 }; struct pci_func *func = *func_passed; - u8 function; - u8 device; + unsigned int devfn; u8 irq; int retval; debug ("%s - enter\n", __FUNCTION__); - function = func->function; - device = func->device; + devfn = PCI_DEVFN(func->function, func->device); + ibmphp_pci_bus->number = func->busno; /* Configuring necessary info for the bridge so that we could see the devices * behind it */ - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_PRIMARY_BUS, func->busno); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, func->busno); /* _____________________For debugging purposes only __________________________ - pci_read_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_PRIMARY_BUS, &pri_number); + pci_bus_config_byte (ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, &pri_number); debug ("primary # written into the bridge is %x\n", pri_number); ___________________________________________________________________________*/ @@ -624,23 +627,23 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) debug ("after find_sec_number, the number we got is %x\n", sec_number); debug ("AFTER FIND_SEC_NUMBER, func->busno IS %x\n", func->busno); - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_SECONDARY_BUS, sec_number); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, sec_number); /* __________________For debugging purposes only __________________________________ - pci_read_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_SECONDARY_BUS, &sec_number); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); debug ("sec_number after write/read is %x\n", sec_number); ________________________________________________________________________________*/ - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_SUBORDINATE_BUS, sec_number); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, sec_number); /* __________________For debugging purposes only ____________________________________ - pci_read_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_SUBORDINATE_BUS, &sec_number); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, &sec_number); debug ("subordinate number after write/read is %x\n", sec_number); __________________________________________________________________________________*/ - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_CACHE_LINE_SIZE, CACHE); - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_LATENCY_TIMER, LATENCY); - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_SEC_LATENCY_TIMER, LATENCY); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_SEC_LATENCY_TIMER, LATENCY); debug ("func->busno is %x\n", func->busno); debug ("sec_number after writing is %x\n", sec_number); @@ -653,8 +656,8 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) /* First we need to allocate mem/io for the bridge itself in case it needs it */ for (count = 0; address[count]; count++) { /* for 2 BARs */ - pci_write_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], 0xFFFFFFFF); - pci_read_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], &bar[count]); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF); + pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]); if (!bar[count]) { /* This BAR is not implemented */ @@ -694,7 +697,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) return -EIO; } - pci_write_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], func->io[count]->start); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->io[count]->start); } else { /* This is Memory */ @@ -747,13 +750,13 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) } } - pci_write_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], func->pfmem[count]->start); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->pfmem[count]->start); if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ count += 1; /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */ - pci_write_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], 0x00000000); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000); } } else { @@ -784,13 +787,13 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) return -EIO; } - pci_write_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], func->mem[count]->start); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->mem[count]->start); if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ count += 1; /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */ - pci_write_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, address[count], 0x00000000); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000); } } @@ -802,6 +805,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) if (amount_needed == NULL) return -ENOMEM; + ibmphp_pci_bus->number = func->busno; debug ("after coming back from scan_behind_bridge\n"); debug ("amount_needed->not_correct = %x\n", amount_needed->not_correct); debug ("amount_needed->io = %x\n", amount_needed->io); @@ -920,16 +924,30 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) debug ("flag_io = %x, flag_mem = %x, flag_pfmem = %x\n", flag_io, flag_mem, flag_pfmem); if (flag_io && flag_mem && flag_pfmem) { - bus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); + /* If on bootup, there was a bridged card in this slot, + * then card was removed and ibmphp got unloaded and loaded + * back again, there's no way for us to remove the bus + * struct, so no need to kmalloc, can use existing node + */ + bus = ibmphp_find_res_bus (sec_number); if (!bus) { - err ("out of system memory \n"); - retval = -ENOMEM; + bus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); + if (!bus) { + err ("out of system memory \n"); + retval = -ENOMEM; + goto error; + } + memset (bus, 0, sizeof (struct bus_node)); + bus->busno = sec_number; + debug ("b4 adding new bus\n"); + rc = add_new_bus (bus, io, mem, pfmem, func->busno); + } else if (!(bus->rangeIO) && !(bus->rangeMem) && !(bus->rangePFMem)) + rc = add_new_bus (bus, io, mem, pfmem, 0xFF); + else { + err ("expected bus structure not empty? \n"); + retval = -EIO; goto error; } - memset (bus, 0, sizeof (struct bus_node)); - bus->busno = sec_number; - debug ("b4 adding new bus\n"); - rc = add_new_bus (bus, io, mem, pfmem, func->busno); if (rc) { if (rc == -ENOMEM) { ibmphp_remove_bus (bus, func->busno); @@ -938,8 +956,8 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) retval = rc; goto error; } - pci_read_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_IO_BASE, &io_base); - pci_read_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_PREF_MEMORY_BASE, &pfmem_base); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, &io_base); + pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &pfmem_base); if ((io_base & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { debug ("io 32\n"); @@ -951,73 +969,73 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno) } if (bus->noIORanges) { - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_IO_BASE, 0x00 | bus->rangeIO->start >> 8); - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_IO_LIMIT, 0x00 | bus->rangeIO->end >> 8); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, 0x00 | bus->rangeIO->start >> 8); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, 0x00 | bus->rangeIO->end >> 8); /* _______________This is for debugging purposes only ____________________ - pci_read_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_IO_BASE, &temp); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, &temp); debug ("io_base = %x\n", (temp & PCI_IO_RANGE_TYPE_MASK) << 8); - pci_read_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_IO_LIMIT, &temp); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, &temp); debug ("io_limit = %x\n", (temp & PCI_IO_RANGE_TYPE_MASK) << 8); ________________________________________________________________________*/ if (need_io_upper) { /* since can't support n.e.ways */ - pci_write_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_IO_BASE_UPPER16, 0x0000); - pci_write_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_IO_LIMIT_UPPER16, 0x0000); + pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_IO_BASE_UPPER16, 0x0000); + pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_IO_LIMIT_UPPER16, 0x0000); } } else { - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_IO_BASE, 0x00); - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_IO_LIMIT, 0x00); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, 0x00); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, 0x00); } if (bus->noMemRanges) { - pci_write_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_MEMORY_BASE, 0x0000 | bus->rangeMem->start >> 16); - pci_write_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_MEMORY_LIMIT, 0x0000 | bus->rangeMem->end >> 16); + pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, 0x0000 | bus->rangeMem->start >> 16); + pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, 0x0000 | bus->rangeMem->end >> 16); /* ____________________This is for debugging purposes only ________________________ - pci_read_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_MEMORY_BASE, &temp); + pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, &temp); debug ("mem_base = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16); - pci_read_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_MEMORY_LIMIT, &temp); + pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, &temp); debug ("mem_limit = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16); __________________________________________________________________________________*/ } else { - pci_write_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_MEMORY_BASE, 0xffff); - pci_write_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_MEMORY_LIMIT, 0x0000); + pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, 0xffff); + pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, 0x0000); } if (bus->noPFMemRanges) { - pci_write_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_PREF_MEMORY_BASE, 0x0000 | bus->rangePFMem->start >> 16); - pci_write_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_PREF_MEMORY_LIMIT, 0x0000 | bus->rangePFMem->end >> 16); + pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, 0x0000 | bus->rangePFMem->start >> 16); + pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, 0x0000 | bus->rangePFMem->end >> 16); /* __________________________This is for debugging purposes only _______________________ - pci_read_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_PREF_MEMORY_BASE, &temp); + pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &temp); debug ("pfmem_base = %x", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16); - pci_read_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_PREF_MEMORY_LIMIT, &temp); + pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &temp); debug ("pfmem_limit = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16); ______________________________________________________________________________________*/ if (need_pfmem_upper) { /* since can't support n.e.ways */ - pci_write_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_PREF_BASE_UPPER32, 0x00000000); - pci_write_config_dword_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_PREF_LIMIT_UPPER32, 0x00000000); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_BASE_UPPER32, 0x00000000); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_LIMIT_UPPER32, 0x00000000); } } else { - pci_write_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_PREF_MEMORY_BASE, 0xffff); - pci_write_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_PREF_MEMORY_LIMIT, 0x0000); + pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, 0xffff); + pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, 0x0000); } debug ("b4 writing control information\n"); - pci_read_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_INTERRUPT_PIN, &irq); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_PIN, &irq); if ((irq > 0x00) && (irq < 0x05)) - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_INTERRUPT_LINE, func->irq[irq - 1]); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_LINE, func->irq[irq - 1]); /* - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_BRIDGE_CONTROL, ctrl); - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_PARITY); - pci_write_config_byte_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_SERR); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, ctrl); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_PARITY); + pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_SERR); */ - pci_write_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_COMMAND, DEVICEENABLE); - pci_write_config_word_nodev (ibmphp_pci_root_ops, func->busno, device, function, PCI_BRIDGE_CONTROL, 0x07); + pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE); + pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, 0x07); for (i = 0; i < 32; i++) { if (amount_needed->devices[i]) { debug ("device where devices[i] is 1 = %x\n", i); @@ -1073,6 +1091,7 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) u16 vendor_id; u8 hdr_type; u8 device, function; + unsigned int devfn; int howmany = 0; /*this is to see if there are any devices behind the bridge */ u32 bar[6], class; @@ -1092,20 +1111,23 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) return NULL; memset (amount, 0, sizeof (struct res_needed)); + ibmphp_pci_bus->number = busno; + debug ("the bus_no behind the bridge is %x\n", busno); debug ("scanning devices behind the bridge...\n"); for (device = 0; device < 32; device++) { amount->devices[device] = 0; for (function = 0; function < 8; function++) { + devfn = PCI_DEVFN(device, function); - pci_read_config_word_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_VENDOR_ID, &vendor_id); + pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id); if (vendor_id != PCI_VENDOR_ID_NOTVALID) { /* found correct device!!! */ howmany++; - pci_read_config_byte_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_HEADER_TYPE, &hdr_type); - pci_read_config_dword_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_CLASS_REVISION, &class); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type); + pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class); debug ("hdr_type behind the bridge is %x\n", hdr_type); if (hdr_type & PCI_HEADER_TYPE_BRIDGE) { @@ -1132,14 +1154,14 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) for (count = 0; address[count]; count++) { /* for 6 BARs */ /* - pci_read_config_byte_nodev(ibmphp_pci_root_ops, busno, device, function, address[count], &tmp); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, address[count], &tmp); if (tmp & 0x01) // IO - pci_write_config_dword_nodev(ibmphp_pci_root_ops, busno, device, function, address[count], 0xFFFFFFFD); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFD); else // MEMORY - pci_write_config_dword_nodev(ibmphp_pci_root_ops, busno, device, function, address[count], 0xFFFFFFFF); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF); */ - pci_write_config_dword_nodev (ibmphp_pci_root_ops, busno, device, function, address[count], 0xFFFFFFFF); - pci_read_config_dword_nodev (ibmphp_pci_root_ops, busno, device, function, address[count], &bar[count]); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF); + pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]); debug ("what is bar[count]? %x, count = %d\n", bar[count], count); @@ -1223,6 +1245,7 @@ static int unconfigure_boot_device (u8 busno, u8 device, u8 function) u32 temp_end; u32 size; u32 tmp_address; + unsigned int devfn; debug ("%s - enter\n", __FUNCTION__); @@ -1232,14 +1255,16 @@ static int unconfigure_boot_device (u8 busno, u8 device, u8 function) return -EINVAL; } + devfn = PCI_DEVFN(device, function); + ibmphp_pci_bus->number = busno; for (count = 0; address[count]; count++) { /* for 6 BARs */ - pci_read_config_dword_nodev (ibmphp_pci_root_ops, busno, device, function, address[count], &start_address); + pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &start_address); /* We can do this here, b/c by that time the device driver of the card has been stopped */ - pci_write_config_dword_nodev (ibmphp_pci_root_ops, busno, device, function, address[count], 0xFFFFFFFF); - pci_read_config_dword_nodev (ibmphp_pci_root_ops, busno, device, function, address[count], &size); - pci_write_config_dword_nodev (ibmphp_pci_root_ops, busno, device, function, address[count], start_address); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF); + pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &size); + pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], start_address); debug ("start_address is %x\n", start_address); debug ("busno, device, function %x %x %x\n", busno, device, function); @@ -1336,13 +1361,16 @@ static int unconfigure_boot_bridge (u8 busno, u8 device, u8 function) PCI_BASE_ADDRESS_1, 0 }; + unsigned int devfn; + devfn = PCI_DEVFN(device, function); + ibmphp_pci_bus->number = busno; bus_no = (int) busno; debug ("busno is %x\n", busno); - pci_read_config_byte_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_PRIMARY_BUS, &pri_number); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, &pri_number); debug ("%s - busno = %x, primary_number = %x\n", __FUNCTION__, busno, pri_number); - pci_read_config_byte_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_SECONDARY_BUS, &sec_number); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); debug ("sec_number is %x\n", sec_number); sec_no = (int) sec_number; pri_no = (int) pri_number; @@ -1351,10 +1379,10 @@ static int unconfigure_boot_bridge (u8 busno, u8 device, u8 function) return -EINVAL; } - pci_read_config_byte_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_SECONDARY_BUS, &sec_number); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); sec_no = (int) sec_no; - pci_read_config_byte_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_SUBORDINATE_BUS, &sub_number); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, &sub_number); sub_no = (int) sub_number; debug ("sub_no is %d, sec_no is %d\n", sub_no, sec_no); if (sec_no != sub_number) { @@ -1374,7 +1402,7 @@ static int unconfigure_boot_bridge (u8 busno, u8 device, u8 function) for (count = 0; address[count]; count++) { /* for 2 BARs */ - pci_read_config_dword_nodev (ibmphp_pci_root_ops, busno, device, function, address[count], &start_address); + pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &start_address); if (!start_address) { /* This BAR is not implemented */ @@ -1447,6 +1475,7 @@ static int unconfigure_boot_card (struct slot *slot_cur) u8 busno; u8 function; int rc; + unsigned int devfn; u8 valid_device = 0x00; /* To see if we are ever able to find valid device and read it */ debug ("%s - enter\n", __FUNCTION__); @@ -1457,8 +1486,10 @@ static int unconfigure_boot_card (struct slot *slot_cur) debug ("b4 for loop, device is %x\n", device); /* For every function on the card */ for (function = 0x0; function < 0x08; function++) { + devfn = PCI_DEVFN(device, function); + ibmphp_pci_bus->number = busno; - pci_read_config_word_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_VENDOR_ID, &vendor_id); + pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id); if (vendor_id != PCI_VENDOR_ID_NOTVALID) { /* found correct device!!! */ @@ -1471,8 +1502,8 @@ static int unconfigure_boot_card (struct slot *slot_cur) * |_=> 0 = single function device, 1 = multi-function device */ - pci_read_config_byte_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_HEADER_TYPE, &hdr_type); - pci_read_config_dword_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_CLASS_REVISION, &class); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type); + pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class); debug ("hdr_type %x, class %x\n", hdr_type, class); class >>= 8; /* to take revision out, class = class.subclass.prog i/f */ @@ -1579,7 +1610,6 @@ int ibmphp_unconfigure_card (struct slot **slot_cur, int the_end) } if (sl->func) { - debug ("do we come in here? \n"); cur_func = sl->func; while (cur_func) { /* TO DO: WILL MOST LIKELY NEED TO GET RID OF THE BUS STRUCTURE FROM RESOURCES AS WELL */ @@ -1619,6 +1649,7 @@ int ibmphp_unconfigure_card (struct slot **slot_cur, int the_end) sl->func = NULL; *slot_cur = sl; + debug ("%s - exit\n", __FUNCTION__); return 0; } @@ -1638,14 +1669,15 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r struct bus_node *cur_bus = NULL; /* Trying to find the parent bus number */ - cur_bus = ibmphp_find_res_bus (parent_busno); - if (!cur_bus) { - err ("strange, cannot find bus which is supposed to be at the system... something is terribly wrong...\n"); - return -ENODEV; + if (parent_busno != 0xFF) { + cur_bus = ibmphp_find_res_bus (parent_busno); + if (!cur_bus) { + err ("strange, cannot find bus which is supposed to be at the system... something is terribly wrong...\n"); + return -ENODEV; + } + + list_add (&bus->bus_list, &cur_bus->bus_list); } - - list_add (&bus->bus_list, &cur_bus->bus_list); - if (io) { io_range = kmalloc (sizeof (struct range_node), GFP_KERNEL); if (!io_range) { @@ -1698,6 +1730,7 @@ static u8 find_sec_number (u8 primary_busno, u8 slotno) int min, max; u8 busno; struct bus_info *bus; + struct bus_node *bus_cur; bus = ibmphp_find_same_bus_num (primary_busno); if (!bus) { @@ -1712,7 +1745,12 @@ static u8 find_sec_number (u8 primary_busno, u8 slotno) } busno = (u8) (slotno - (u8) min); busno += primary_busno + 0x01; - if (!ibmphp_find_res_bus (busno)) + bus_cur = ibmphp_find_res_bus (busno); + /* either there is no such bus number, or there are no ranges, which + * can only happen if we removed the bridged device in previous load + * of the driver, and now only have the skeleton bus struct + */ + if ((!bus_cur) || (!(bus_cur->rangeIO) && !(bus_cur->rangeMem) && !(bus_cur->rangePFMem))) return busno; return 0xff; } diff --git a/drivers/hotplug/ibmphp_res.c b/drivers/hotplug/ibmphp_res.c index 0cf06e48e078..762ad60c71a7 100644 --- a/drivers/hotplug/ibmphp_res.c +++ b/drivers/hotplug/ibmphp_res.c @@ -45,11 +45,17 @@ static void fix_resources (struct bus_node *); static inline struct bus_node *find_bus_wprev (u8, struct bus_node **, u8); static LIST_HEAD(gbuses); +LIST_HEAD(ibmphp_res_head); -static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr) +static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr, u8 busno, int flag) { struct bus_node * newbus; + if (!(curr) && !(flag)) { + err ("NULL pointer passed \n"); + return NULL; + } + newbus = kmalloc (sizeof (struct bus_node), GFP_KERNEL); if (!newbus) { err ("out of system memory \n"); @@ -57,14 +63,24 @@ static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr) } memset (newbus, 0, sizeof (struct bus_node)); - newbus->busno = curr->bus_num; + if (flag) + newbus->busno = busno; + else + newbus->busno = curr->bus_num; list_add_tail (&newbus->bus_list, &gbuses); return newbus; } static struct resource_node * __init alloc_resources (struct ebda_pci_rsrc * curr) { - struct resource_node *rs = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + struct resource_node *rs; + + if (!curr) { + err ("NULL passed to allocate \n"); + return NULL; + } + + rs = kmalloc (sizeof (struct resource_node), GFP_KERNEL); if (!rs) { err ("out of system memory \n"); return NULL; @@ -299,7 +315,7 @@ int __init ibmphp_rsrc_init (void) * actually appears... */ if (ibmphp_add_resource (new_mem) < 0) { - newbus = alloc_error_bus (curr); + newbus = alloc_error_bus (curr, 0, 0); if (!newbus) return -ENOMEM; newbus->firstMem = new_mem; @@ -316,7 +332,7 @@ int __init ibmphp_rsrc_init (void) new_pfmem->type = PFMEM; new_pfmem->fromMem = FALSE; if (ibmphp_add_resource (new_pfmem) < 0) { - newbus = alloc_error_bus (curr); + newbus = alloc_error_bus (curr, 0, 0); if (!newbus) return -ENOMEM; newbus->firstPFMem = new_pfmem; @@ -340,7 +356,7 @@ int __init ibmphp_rsrc_init (void) * range actually appears... */ if (ibmphp_add_resource (new_io) < 0) { - newbus = alloc_error_bus (curr); + newbus = alloc_error_bus (curr, 0, 0); if (!newbus) return -ENOMEM; newbus->firstIO = new_io; @@ -352,8 +368,6 @@ int __init ibmphp_rsrc_init (void) } } - debug ("after the while loop in rsrc_init \n"); - list_for_each (tmp, &gbuses) { bus_cur = list_entry (tmp, struct bus_node, bus_list); /* This is to get info about PPB resources, since EBDA doesn't put this info into the primary bus info */ @@ -361,11 +375,9 @@ int __init ibmphp_rsrc_init (void) if (rc) return rc; } - debug ("b4 once_over in rsrc_init \n"); rc = once_over (); /* This is to align ranges (so no -1) */ if (rc) return rc; - debug ("after once_over in rsrc_init \n"); return 0; } @@ -580,7 +592,7 @@ static void fix_resources (struct bus_node *bus_cur) * based on their resource type and sorted by their starting addresses. It assigns * the ptrs to next and nextRange if needed. * - * Input: 3 diff. resources (nulled out if not needed) + * Input: resource ptr * Output: ptrs assigned (to the node) * 0 or -1 *******************************************************************************/ @@ -593,12 +605,17 @@ int ibmphp_add_resource (struct resource_node *res) struct resource_node *res_start = NULL; debug ("%s - enter\n", __FUNCTION__); + + if (!res) { + err ("NULL passed to add \n"); + return -ENODEV; + } bus_cur = find_bus_wprev (res->busno, NULL, 0); if (!bus_cur) { /* didn't find a bus, smth's wrong!!! */ - err ("no bus in the system, either pci_dev's wrong or allocation failed\n"); + debug ("no bus in the system, either pci_dev's wrong or allocation failed\n"); return -ENODEV; } @@ -769,6 +786,11 @@ int ibmphp_remove_resource (struct resource_node *res) struct resource_node *mem_cur; char * type = ""; + if (!res) { + err ("resource to remove is NULL \n"); + return -ENODEV; + } + bus_cur = find_bus_wprev (res->busno, NULL, 0); if (!bus_cur) { @@ -797,7 +819,6 @@ int ibmphp_remove_resource (struct resource_node *res) res_prev = NULL; while (res_cur) { - /* ???????????DO WE _NEED_ TO BE CHECKING FOR END AS WELL?????????? */ if ((res_cur->start == res->start) && (res_cur->end == res->end)) break; res_prev = res_cur; @@ -981,7 +1002,7 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge) if (!bus_cur) { /* didn't find a bus, smth's wrong!!! */ - err ("no bus in the system, either pci_dev's wrong or allocation failed \n"); + debug ("no bus in the system, either pci_dev's wrong or allocation failed \n"); return -EINVAL; } @@ -1340,7 +1361,7 @@ int ibmphp_remove_bus (struct bus_node *bus, u8 parent_busno) prev_bus = find_bus_wprev (parent_busno, NULL, 0); if (!prev_bus) { - err ("something terribly wrong. Cannot find parent bus to the one to remove\n"); + debug ("something terribly wrong. Cannot find parent bus to the one to remove\n"); return -ENODEV; } @@ -1467,13 +1488,18 @@ static int remove_ranges (struct bus_node *bus_cur, struct bus_node *bus_prev) /* * find the resource node in the bus - * Input: Resource needed, start address of the resource, type or resource + * Input: Resource needed, start address of the resource, type of resource */ int ibmphp_find_resource (struct bus_node *bus, u32 start_address, struct resource_node **res, int flag) { struct resource_node *res_cur = NULL; char * type = ""; + if (!bus) { + err ("The bus passed in NULL to find resource \n"); + return -ENODEV; + } + switch (flag) { case IO: res_cur = bus->firstIO; @@ -1514,11 +1540,11 @@ int ibmphp_find_resource (struct bus_node *bus, u32 start_address, struct resour res_cur = res_cur->next; } if (!res_cur) { - err ("SOS...cannot find %s resource in the bus. \n", type); + debug ("SOS...cannot find %s resource in the bus. \n", type); return -EINVAL; } } else { - err ("SOS... cannot find %s resource in the bus. \n", type); + debug ("SOS... cannot find %s resource in the bus. \n", type); return -EINVAL; } } @@ -1756,6 +1782,8 @@ void ibmphp_print_test (void) struct range_node *range; struct resource_node *res; struct list_head *tmp; + + debug_pci ("*****************START**********************\n"); if ((!list_empty(&gbuses)) && flags) { err ("The GBUSES is not NULL?!?!?!?!?\n"); @@ -1764,50 +1792,50 @@ void ibmphp_print_test (void) list_for_each (tmp, &gbuses) { bus_cur = list_entry (tmp, struct bus_node, bus_list); - debug ("This is bus # %d. There are \n", bus_cur->busno); - debug ("IORanges = %d\t", bus_cur->noIORanges); - debug ("MemRanges = %d\t", bus_cur->noMemRanges); - debug ("PFMemRanges = %d\n", bus_cur->noPFMemRanges); - debug ("The IO Ranges are as follows:\n"); + debug_pci ("This is bus # %d. There are \n", bus_cur->busno); + debug_pci ("IORanges = %d\t", bus_cur->noIORanges); + debug_pci ("MemRanges = %d\t", bus_cur->noMemRanges); + debug_pci ("PFMemRanges = %d\n", bus_cur->noPFMemRanges); + debug_pci ("The IO Ranges are as follows:\n"); if (bus_cur->rangeIO) { range = bus_cur->rangeIO; for (i = 0; i < bus_cur->noIORanges; i++) { - debug ("rangeno is %d\n", range->rangeno); - debug ("[%x - %x]\n", range->start, range->end); + debug_pci ("rangeno is %d\n", range->rangeno); + debug_pci ("[%x - %x]\n", range->start, range->end); range = range->next; } } - debug ("The Mem Ranges are as follows:\n"); + debug_pci ("The Mem Ranges are as follows:\n"); if (bus_cur->rangeMem) { range = bus_cur->rangeMem; for (i = 0; i < bus_cur->noMemRanges; i++) { - debug ("rangeno is %d\n", range->rangeno); - debug ("[%x - %x]\n", range->start, range->end); + debug_pci ("rangeno is %d\n", range->rangeno); + debug_pci ("[%x - %x]\n", range->start, range->end); range = range->next; } } - debug ("The PFMem Ranges are as follows:\n"); + debug_pci ("The PFMem Ranges are as follows:\n"); if (bus_cur->rangePFMem) { range = bus_cur->rangePFMem; for (i = 0; i < bus_cur->noPFMemRanges; i++) { - debug ("rangeno is %d\n", range->rangeno); - debug ("[%x - %x]\n", range->start, range->end); + debug_pci ("rangeno is %d\n", range->rangeno); + debug_pci ("[%x - %x]\n", range->start, range->end); range = range->next; } } - debug ("The resources on this bus are as follows\n"); + debug_pci ("The resources on this bus are as follows\n"); - debug ("IO...\n"); + debug_pci ("IO...\n"); if (bus_cur->firstIO) { res = bus_cur->firstIO; while (res) { - debug ("The range # is %d\n", res->rangeno); - debug ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); - debug ("[%x - %x], len=%x\n", res->start, res->end, res->len); + debug_pci ("The range # is %d\n", res->rangeno); + debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); + debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len); if (res->next) res = res->next; else if (res->nextRange) @@ -1816,13 +1844,13 @@ void ibmphp_print_test (void) break; } } - debug ("Mem...\n"); + debug_pci ("Mem...\n"); if (bus_cur->firstMem) { res = bus_cur->firstMem; while (res) { - debug ("The range # is %d\n", res->rangeno); - debug ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); - debug ("[%x - %x], len=%x\n", res->start, res->end, res->len); + debug_pci ("The range # is %d\n", res->rangeno); + debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); + debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len); if (res->next) res = res->next; else if (res->nextRange) @@ -1831,13 +1859,13 @@ void ibmphp_print_test (void) break; } } - debug ("PFMem...\n"); + debug_pci ("PFMem...\n"); if (bus_cur->firstPFMem) { res = bus_cur->firstPFMem; while (res) { - debug ("The range # is %d\n", res->rangeno); - debug ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); - debug ("[%x - %x], len=%x\n", res->start, res->end, res->len); + debug_pci ("The range # is %d\n", res->rangeno); + debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); + debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len); if (res->next) res = res->next; else if (res->nextRange) @@ -1847,23 +1875,53 @@ void ibmphp_print_test (void) } } - debug ("PFMemFromMem...\n"); + debug_pci ("PFMemFromMem...\n"); if (bus_cur->firstPFMemFromMem) { res = bus_cur->firstPFMemFromMem; while (res) { - debug ("The range # is %d\n", res->rangeno); - debug ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); - debug ("[%x - %x], len=%x\n", res->start, res->end, res->len); + debug_pci ("The range # is %d\n", res->rangeno); + debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc); + debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len); res = res->next; } } } + debug_pci ("***********************END***********************\n"); +} + +int static range_exists_already (struct range_node * range, struct bus_node * bus_cur, u8 type) +{ + struct range_node * range_cur = NULL; + switch (type) { + case IO: + range_cur = bus_cur->rangeIO; + break; + case MEM: + range_cur = bus_cur->rangeMem; + break; + case PFMEM: + range_cur = bus_cur->rangePFMem; + break; + default: + err ("wrong type passed to find out if range already exists \n"); + return -ENODEV; + } + + while (range_cur) { + if ((range_cur->start == range->start) && (range_cur->end == range->end)) + return 1; + range_cur = range_cur->next; + } + + return 0; } /* This routine will read the windows for any PPB we have and update the * range info for the secondary bus, and will also input this info into * primary bus, since BIOS doesn't. This is for PPB that are in the system - * on bootup + * on bootup. For bridged cards that were added during previous load of the + * driver, only the ranges and the bus structure are added, the devices are + * added from NVRAM * Input: primary busno * Returns: none * Note: this function doesn't take into account IO restrictions etc, @@ -1874,7 +1932,7 @@ void ibmphp_print_test (void) */ static int __init update_bridge_ranges (struct bus_node **bus) { - u8 sec_busno, device, function, busno, hdr_type, start_io_address, end_io_address; + u8 sec_busno, device, function, hdr_type, start_io_address, end_io_address; u16 vendor_id, upper_io_start, upper_io_end, start_mem_address, end_mem_address; u32 start_address, end_address, upper_start, upper_end; struct bus_node *bus_sec; @@ -1883,19 +1941,24 @@ static int __init update_bridge_ranges (struct bus_node **bus) struct resource_node *mem; struct resource_node *pfmem; struct range_node *range; + unsigned int devfn; + bus_cur = *bus; - busno = bus_cur->busno; + if (!bus_cur) + return -ENODEV; + ibmphp_pci_bus->number = bus_cur->busno; debug ("inside %s \n", __FUNCTION__); debug ("bus_cur->busno = %x\n", bus_cur->busno); for (device = 0; device < 32; device++) { for (function = 0x00; function < 0x08; function++) { - pci_read_config_word_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_VENDOR_ID, &vendor_id); + devfn = PCI_DEVFN(device, function); + pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id); if (vendor_id != PCI_VENDOR_ID_NOTVALID) { /* found correct device!!! */ - pci_read_config_byte_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_HEADER_TYPE, &hdr_type); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type); switch (hdr_type) { case PCI_HEADER_TYPE_NORMAL: @@ -1914,21 +1977,25 @@ static int __init update_bridge_ranges (struct bus_node **bus) temp++; } */ - pci_read_config_byte_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_SECONDARY_BUS, &sec_busno); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_busno); bus_sec = find_bus_wprev (sec_busno, NULL, 0); - pci_read_config_byte_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_IO_BASE, &start_io_address); - pci_read_config_byte_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_IO_LIMIT, &end_io_address); - pci_read_config_word_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_IO_BASE_UPPER16, &upper_io_start); - pci_read_config_word_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_IO_LIMIT_UPPER16, &upper_io_end); + /* this bus structure doesn't exist yet, PPB was configured during previous loading of ibmphp */ + if (!bus_sec) { + bus_sec = alloc_error_bus (NULL, sec_busno, 1); + /* the rest will be populated during NVRAM call */ + return 0; + } + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, &start_io_address); + pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, &end_io_address); + pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_IO_BASE_UPPER16, &upper_io_start); + pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_IO_LIMIT_UPPER16, &upper_io_end); start_address = (start_io_address & PCI_IO_RANGE_MASK) << 8; start_address |= (upper_io_start << 16); end_address = (end_io_address & PCI_IO_RANGE_MASK) << 8; end_address |= (upper_io_end << 16); if ((start_address) && (start_address <= end_address)) { - range = kmalloc (sizeof (struct range_node), GFP_KERNEL); - if (!range) { err ("out of system memory \n"); return -ENOMEM; @@ -1937,36 +2004,42 @@ static int __init update_bridge_ranges (struct bus_node **bus) range->start = start_address; range->end = end_address + 0xfff; - if (bus_sec->noIORanges > 0) - add_range (IO, range, bus_sec); - else { + if (bus_sec->noIORanges > 0) { + if (!range_exists_already (range, bus_sec, IO)) { + add_range (IO, range, bus_sec); + ++bus_sec->noIORanges; + } else { + kfree (range); + range = NULL; + } + } else { /* 1st IO Range on the bus */ range->rangeno = 1; bus_sec->rangeIO = range; + ++bus_sec->noIORanges; } - - ++bus_sec->noIORanges; fix_resources (bus_sec); - - io = kmalloc (sizeof (struct resource_node), GFP_KERNEL); - if (!io) { - kfree (range); - err ("out of system memory \n"); - return -ENOMEM; + + if (ibmphp_find_resource (bus_cur, start_address, &io, IO)) { + io = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + if (!io) { + kfree (range); + err ("out of system memory \n"); + return -ENOMEM; + } + memset (io, 0, sizeof (struct resource_node)); + io->type = IO; + io->busno = bus_cur->busno; + io->devfunc = ((device << 3) | (function & 0x7)); + io->start = start_address; + io->end = end_address + 0xfff; + io->len = io->end - io->start + 1; + ibmphp_add_resource (io); } - memset (io, 0, sizeof (struct resource_node)); - io->type = IO; - io->busno = bus_cur->busno; - io->devfunc = ((device << 3) | (function & 0x7)); - io->start = start_address; - io->end = end_address + 0xfff; - io->len = io->end - io->start + 1; - - ibmphp_add_resource (io); - } + } - pci_read_config_word_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_MEMORY_BASE, &start_mem_address); - pci_read_config_word_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_MEMORY_LIMIT, &end_mem_address); + pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, &start_mem_address); + pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, &end_mem_address); start_address = 0x00000000 | (start_mem_address & PCI_MEMORY_RANGE_MASK) << 16; end_address = 0x00000000 | (end_mem_address & PCI_MEMORY_RANGE_MASK) << 16; @@ -1982,36 +2055,44 @@ static int __init update_bridge_ranges (struct bus_node **bus) range->start = start_address; range->end = end_address + 0xfffff; - if (bus_sec->noMemRanges > 0) - add_range (MEM, range, bus_sec); - else { + if (bus_sec->noMemRanges > 0) { + if (!range_exists_already (range, bus_sec, MEM)) { + add_range (MEM, range, bus_sec); + ++bus_sec->noMemRanges; + } else { + kfree (range); + range = NULL; + } + } else { /* 1st Mem Range on the bus */ range->rangeno = 1; bus_sec->rangeMem = range; + ++bus_sec->noMemRanges; } - ++bus_sec->noMemRanges; fix_resources (bus_sec); - mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); - if (!mem) { - kfree (range); - err ("out of system memory \n"); - return -ENOMEM; + if (ibmphp_find_resource (bus_cur, start_address, &mem, MEM)) { + mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + if (!mem) { + kfree (range); + err ("out of system memory \n"); + return -ENOMEM; + } + memset (mem, 0, sizeof (struct resource_node)); + mem->type = MEM; + mem->busno = bus_cur->busno; + mem->devfunc = ((device << 3) | (function & 0x7)); + mem->start = start_address; + mem->end = end_address + 0xfffff; + mem->len = mem->end - mem->start + 1; + ibmphp_add_resource (mem); } - memset (mem, 0, sizeof (struct resource_node)); - mem->type = MEM; - mem->busno = bus_cur->busno; - mem->devfunc = ((device << 3) | (function & 0x7)); - mem->start = start_address; - mem->end = end_address + 0xfffff; - mem->len = mem->end - mem->start + 1; - ibmphp_add_resource (mem); } - pci_read_config_word_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_PREF_MEMORY_BASE, &start_mem_address); - pci_read_config_word_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_PREF_MEMORY_LIMIT, &end_mem_address); - pci_read_config_dword_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_PREF_BASE_UPPER32, &upper_start); - pci_read_config_dword_nodev (ibmphp_pci_root_ops, busno, device, function, PCI_PREF_LIMIT_UPPER32, &upper_end); + pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &start_mem_address); + pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &end_mem_address); + pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_BASE_UPPER32, &upper_start); + pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_LIMIT_UPPER32, &upper_end); start_address = 0x00000000 | (start_mem_address & PCI_MEMORY_RANGE_MASK) << 16; end_address = 0x00000000 | (end_mem_address & PCI_MEMORY_RANGE_MASK) << 16; #if BITS_PER_LONG == 64 @@ -2030,32 +2111,40 @@ static int __init update_bridge_ranges (struct bus_node **bus) range->start = start_address; range->end = end_address + 0xfffff; - if (bus_sec->noPFMemRanges > 0) - add_range (PFMEM, range, bus_sec); - else { + if (bus_sec->noPFMemRanges > 0) { + if (!range_exists_already (range, bus_sec, PFMEM)) { + add_range (PFMEM, range, bus_sec); + ++bus_sec->noPFMemRanges; + } else { + kfree (range); + range = NULL; + } + } else { /* 1st PFMem Range on the bus */ range->rangeno = 1; bus_sec->rangePFMem = range; + ++bus_sec->noPFMemRanges; } - ++bus_sec->noPFMemRanges; fix_resources (bus_sec); - - pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); - if (!pfmem) { - kfree (range); - err ("out of system memory \n"); - return -ENOMEM; + if (ibmphp_find_resource (bus_cur, start_address, &pfmem, PFMEM)) { + pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL); + if (!pfmem) { + kfree (range); + err ("out of system memory \n"); + return -ENOMEM; + } + memset (pfmem, 0, sizeof (struct resource_node)); + pfmem->type = PFMEM; + pfmem->busno = bus_cur->busno; + pfmem->devfunc = ((device << 3) | (function & 0x7)); + pfmem->start = start_address; + pfmem->end = end_address + 0xfffff; + pfmem->len = pfmem->end - pfmem->start + 1; + pfmem->fromMem = FALSE; + + ibmphp_add_resource (pfmem); } - memset (pfmem, 0, sizeof (struct resource_node)); - pfmem->type = PFMEM; - pfmem->busno = bus_cur->busno; - pfmem->devfunc = ((device << 3) | (function & 0x7)); - pfmem->start = start_address; - pfmem->end = end_address + 0xfffff; - pfmem->len = pfmem->end - pfmem->start + 1; - pfmem->fromMem = FALSE; - ibmphp_add_resource (pfmem); } break; } /* end of switch */ diff --git a/drivers/hotplug/pci_hotplug.h b/drivers/hotplug/pci_hotplug.h index 4ca357f6590a..ae13d0c7ee5b 100644 --- a/drivers/hotplug/pci_hotplug.h +++ b/drivers/hotplug/pci_hotplug.h @@ -141,20 +141,5 @@ extern int pci_visit_dev (struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_parent); -extern int pci_read_config_byte_nodev (struct pci_ops *ops, u8 bus, u8 device, - u8 function, int where, u8 *val); -extern int pci_read_config_word_nodev (struct pci_ops *ops, u8 bus, u8 device, - u8 function, int where, u16 *val); -extern int pci_read_config_dword_nodev (struct pci_ops *ops, u8 bus, u8 device, - u8 function, int where, u32 *val); - -extern int pci_write_config_byte_nodev (struct pci_ops *ops, u8 bus, u8 device, - u8 function, int where, u8 val); -extern int pci_write_config_word_nodev (struct pci_ops *ops, u8 bus, u8 device, - u8 function, int where, u16 val); -extern int pci_write_config_dword_nodev (struct pci_ops *ops, u8 bus, u8 device, - u8 function, int where, u32 val); - - #endif diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 579edc49e82a..14b5dcb183bf 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -6,10 +6,8 @@ export-objs := access.o hotplug.o pci-driver.o pci.o pool.o \ probe.o proc.o search.o compat.o obj-y += access.o probe.o pci.o pool.o quirks.o \ - compat.o names.o pci-driver.o search.o + compat.o names.o pci-driver.o search.o hotplug.o obj-$(CONFIG_PM) += power.o -obj-$(CONFIG_HOTPLUG) += hotplug.o - obj-$(CONFIG_PROC_FS) += proc.o ifndef CONFIG_SPARC64 diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c index 63dc49410dbc..c493d2f0216f 100644 --- a/drivers/pci/hotplug.c +++ b/drivers/pci/hotplug.c @@ -7,8 +7,8 @@ #define TRUE (!FALSE) #endif -static void -run_sbin_hotplug(struct pci_dev *pdev, int insert) +#ifdef CONFIG_HOTPLUG +static void run_sbin_hotplug(struct pci_dev *pdev, int insert) { int i; char *argv[3], *envp[8]; @@ -45,13 +45,18 @@ run_sbin_hotplug(struct pci_dev *pdev, int insert) call_usermodehelper (argv [0], argv, envp); } +#else +static void run_sbin_hotplug(struct pci_dev *pdev, int insert) { } +#endif /** - * pci_insert_device - insert a hotplug device + * pci_insert_device - insert a pci device * @dev: the device to insert * @bus: where to insert it * - * Add a new device to the device lists and notify userspace (/sbin/hotplug). + * Link the device to both the global PCI device chain and the + * per-bus list of devices, add the /proc entry, and notify + * userspace (/sbin/hotplug). */ void pci_insert_device(struct pci_dev *dev, struct pci_bus *bus) @@ -78,11 +83,11 @@ pci_free_resources(struct pci_dev *dev) } /** - * pci_remove_device - remove a hotplug device + * pci_remove_device - remove a pci device * @dev: the device to remove * - * Delete the device structure from the device lists and - * notify userspace (/sbin/hotplug). + * Delete the device structure from the device lists, + * remove the /proc entry, and notify userspace (/sbin/hotplug). */ void pci_remove_device(struct pci_dev *dev) @@ -94,10 +99,11 @@ pci_remove_device(struct pci_dev *dev) #ifdef CONFIG_PROC_FS pci_proc_detach_device(dev); #endif - /* notify userspace of hotplug device removal */ run_sbin_hotplug(dev, FALSE); } +#ifdef CONFIG_HOTPLUG EXPORT_SYMBOL(pci_insert_device); EXPORT_SYMBOL(pci_remove_device); +#endif diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6460e5f08eda..dcb4afa71840 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -479,10 +479,10 @@ struct pci_dev * __devinit pci_scan_slot(struct pci_dev *temp) /* * Link the device to both the global PCI device chain and - * the per-bus list of devices. + * the per-bus list of devices and call /sbin/hotplug if we + * should. */ - list_add_tail(&dev->global_list, &pci_devices); - list_add_tail(&dev->bus_list, &bus->devices); + pci_insert_device (dev, bus); /* Fix up broken headers */ pci_fixup_device(PCI_FIXUP_HEADER, dev); @@ -594,4 +594,5 @@ EXPORT_SYMBOL(pci_setup_device); EXPORT_SYMBOL(pci_add_new_bus); EXPORT_SYMBOL(pci_do_scan_bus); EXPORT_SYMBOL(pci_scan_slot); +EXPORT_SYMBOL(pci_scan_bus); #endif diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 67c7e1feb732..582fac9f16f7 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -18,6 +18,8 @@ #define PCI_CFG_SPACE_SIZE 256 +static int proc_initialized; /* = 0 */ + static loff_t proc_bus_pci_lseek(struct file *file, loff_t off, int whence) { @@ -410,6 +412,9 @@ int pci_proc_attach_device(struct pci_dev *dev) struct proc_dir_entry *de, *e; char name[16]; + if (!proc_initialized) + return -EACCES; + if (!(de = bus->procdir)) { sprintf(name, "%02x", bus->number); de = bus->procdir = proc_mkdir(name, proc_bus_pci_dir); @@ -446,6 +451,9 @@ int pci_proc_attach_bus(struct pci_bus* bus) { struct proc_dir_entry *de = bus->procdir; + if (!proc_initialized) + return -EACCES; + if (!de) { char name[16]; sprintf(name, "%02x", bus->number); @@ -595,6 +603,7 @@ static int __init pci_proc_init(void) entry = create_proc_entry("devices", 0, proc_bus_pci_dir); if (entry) entry->proc_fops = &proc_bus_pci_dev_operations; + proc_initialized = 1; pci_for_each_dev(dev) { pci_proc_attach_device(dev); } diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 5537baa9739d..7145e151e1f8 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1020,6 +1020,16 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) if (status) return status; + /* increment urb's reference count as part of giving it to the HCD + * (which now controls it). HCD guarantees that it either returns + * an error or calls giveback(), but not both. + */ + urb = usb_get_urb (urb); + if (urb->dev == hcd->self.root_hub) { + urb->transfer_flags |= URB_NO_DMA_MAP; + return rh_urb_enqueue (hcd, urb); + } + /* lower level hcd code should use *_dma exclusively */ if (!(urb->transfer_flags & URB_NO_DMA_MAP)) { if (usb_pipecontrol (urb->pipe)) @@ -1038,16 +1048,7 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) : PCI_DMA_TODEVICE); } - /* increment urb's reference count as part of giving it to the HCD - * (which now controls it). HCD guarantees that it either returns - * an error or calls giveback(), but not both. - */ - urb = usb_get_urb (urb); - if (urb->dev == hcd->self.root_hub) - status = rh_urb_enqueue (hcd, urb); - else - status = hcd->driver->urb_enqueue (hcd, urb, mem_flags); - return status; + return hcd->driver->urb_enqueue (hcd, urb, mem_flags); } /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 6e8be7d8f115..a25f9865d6a7 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -27,7 +27,6 @@ /*****************************************************************************/ -#define __NO_VERSION__ #include <linux/config.h> #include <linux/module.h> #include <linux/fs.h> @@ -561,35 +560,57 @@ static void put_mount (struct vfsmount **mount) static int create_special_files (void) { struct dentry *parent; - int retval; + int retval = 0; /* create the devices special file */ retval = get_mount (&usbdevice_fs_type, &usbdevfs_mount); - if (retval) - return retval; + if (retval) { + err ("Unable to get usbdevfs mount"); + goto exit; + } + retval = get_mount (&usb_fs_type, &usbfs_mount); if (retval) { - put_mount (&usbfs_mount); - return retval; + err ("Unable to get usbfs mount"); + goto error_clean_usbdevfs_mount; } + parent = usbfs_mount->mnt_sb->s_root; - devices_usbfs_dentry = fs_create_file ("devices", listmode | S_IFREG, parent, + devices_usbfs_dentry = fs_create_file ("devices", + listmode | S_IFREG, parent, NULL, &usbdevfs_devices_fops, listuid, listgid); if (devices_usbfs_dentry == NULL) { err ("Unable to create devices usbfs file"); - return -ENODEV; + retval = -ENODEV; + goto error_clean_mounts; } + parent = usbdevfs_mount->mnt_sb->s_root; - devices_usbdevfs_dentry = fs_create_file ("devices", listmode | S_IFREG, parent, + devices_usbdevfs_dentry = fs_create_file ("devices", + listmode | S_IFREG, parent, NULL, &usbdevfs_devices_fops, listuid, listgid); if (devices_usbdevfs_dentry == NULL) { err ("Unable to create devices usbfs file"); - return -ENODEV; + retval = -ENODEV; + goto error_remove_file; } - return 0; + goto exit; + +error_remove_file: + fs_remove_file (devices_usbfs_dentry); + devices_usbfs_dentry = NULL; + +error_clean_mounts: + put_mount (&usbfs_mount); + +error_clean_usbdevfs_mount: + put_mount (&usbdevfs_mount); + +exit: + return retval; } static void remove_special_files (void) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 3cfed588b719..32d40841f232 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -57,7 +57,7 @@ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) strcat(buf, tmp); } dbg ("%s: %s portroute %s", - ehci->hcd.self.bus_name, label, + hcd_to_bus (&ehci->hcd)->bus_name, label, buf); } } @@ -122,7 +122,8 @@ dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) } } -static int dbg_status_buf (char *buf, unsigned len, char *label, u32 status) +static int __attribute__((__unused__)) +dbg_status_buf (char *buf, unsigned len, char *label, u32 status) { return snprintf (buf, len, "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s", @@ -140,7 +141,8 @@ static int dbg_status_buf (char *buf, unsigned len, char *label, u32 status) ); } -static int dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable) +static int __attribute__((__unused__)) +dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable) { return snprintf (buf, len, "%s%sintrenable %02x%s%s%s%s%s%s", @@ -213,19 +215,19 @@ dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) static inline int __attribute__((__unused__)) dbg_status_buf (char *buf, unsigned len, char *label, u32 status) -{} +{ return 0; } static inline int __attribute__((__unused__)) dbg_command_buf (char *buf, unsigned len, char *label, u32 command) -{} +{ return 0; } static inline int __attribute__((__unused__)) dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable) -{} +{ return 0; } static inline int __attribute__((__unused__)) dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status) -{} +{ return 0; } #endif /* DEBUG */ @@ -248,7 +250,16 @@ dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status) dbg ("%s", _buf); \ } -#ifdef DEBUG +/*-------------------------------------------------------------------------*/ + +#ifdef STUB_DEBUG_FILES + +static inline void create_debug_files (struct ehci_hcd *bus) { } +static inline void remove_debug_files (struct ehci_hcd *bus) { } + +#else + +/* troubleshooting help: expose state in driverfs */ #define speed_char(info1) ({ char tmp; \ switch (info1 & (3 << 12)) { \ @@ -258,6 +269,49 @@ dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status) default: tmp = '?'; break; \ }; tmp; }) +static void qh_lines (struct ehci_qh *qh, char **nextp, unsigned *sizep) +{ + u32 scratch; + struct list_head *entry; + struct ehci_qtd *td; + unsigned temp; + unsigned size = *sizep; + char *next = *nextp; + + scratch = cpu_to_le32p (&qh->hw_info1); + temp = snprintf (next, size, "qh/%p dev%d %cs ep%d %08x %08x", + qh, scratch & 0x007f, + speed_char (scratch), + (scratch >> 8) & 0x000f, + scratch, cpu_to_le32p (&qh->hw_info2)); + size -= temp; + next += temp; + + list_for_each (entry, &qh->qtd_list) { + td = list_entry (entry, struct ehci_qtd, + qtd_list); + scratch = cpu_to_le32p (&td->hw_token); + temp = snprintf (next, size, + "\n\ttd/%p %s len=%d %08x urb %p", + td, ({ char *tmp; + switch ((scratch>>8)&0x03) { + case 0: tmp = "out"; break; + case 1: tmp = "in"; break; + case 2: tmp = "setup"; break; + default: tmp = "?"; break; + } tmp;}), + (scratch >> 16) & 0x7fff, + scratch, + td->urb); + size -= temp; + next += temp; + } + + temp = snprintf (next, size, "\n"); + *sizep = size - temp; + *nextp = next + temp; +} + static ssize_t show_async (struct device *dev, char *buf, size_t count, loff_t off) { @@ -284,49 +338,21 @@ show_async (struct device *dev, char *buf, size_t count, loff_t off) if (ehci->async) { qh = ehci->async; do { - u32 scratch; - struct list_head *entry; - struct ehci_qtd *td; - - scratch = cpu_to_le32p (&qh->hw_info1); - temp = snprintf (next, size, "qh %p dev%d %cs ep%d", - qh, scratch & 0x007f, - speed_char (scratch), - (scratch >> 8) & 0x000f); - size -= temp; - next += temp; - - list_for_each (entry, &qh->qtd_list) { - td = list_entry (entry, struct ehci_qtd, - qtd_list); - scratch = cpu_to_le32p (&td->hw_token); - temp = snprintf (next, size, - ", td %p len=%d tok %04x %s", - td, scratch >> 16, - scratch & 0xffff, - ({ char *tmp; - switch ((scratch>>8)&0x03) { - case 0: tmp = "out"; break; - case 1: tmp = "in"; break; - case 2: tmp = "setup"; break; - default: tmp = "?"; break; - } tmp;}) - ); - size -= temp; - next += temp; - } - - temp = snprintf (next, size, "\n"); - size -= temp; - next += temp; - + qh_lines (qh, &next, &size); } while ((qh = qh->qh_next.qh) != ehci->async); } + if (ehci->reclaim) { + temp = snprintf (next, size, "\nreclaim =\n"); + size -= temp; + next += temp; + + qh_lines (ehci->reclaim, &next, &size); + } spin_unlock_irqrestore (&ehci->lock, flags); return count - size; } -static DEVICE_ATTR (async, S_IRUSR, show_async, NULL); +static DEVICE_ATTR (async, S_IRUGO, show_async, NULL); #define DBG_SCHED_LIMIT 64 @@ -373,7 +399,7 @@ show_periodic (struct device *dev, char *buf, size_t count, loff_t off) do { switch (tag) { case Q_TYPE_QH: - temp = snprintf (next, size, " intr-%d %p", + temp = snprintf (next, size, " qh%d/%p", p.qh->period, p.qh); size -= temp; next += temp; @@ -387,12 +413,14 @@ show_periodic (struct device *dev, char *buf, size_t count, loff_t off) &p.qh->hw_info1); temp = snprintf (next, size, - " (%cs dev%d ep%d)", + " (%cs dev%d ep%d [%d/%d] %d)", speed_char (scratch), scratch & 0x007f, - (scratch >> 8) & 0x000f); + (scratch >> 8) & 0x000f, + p.qh->usecs, p.qh->c_usecs, + scratch >> 16); - /* FIXME TDs too */ + /* FIXME TD info too */ if (seen_count < DBG_SCHED_LIMIT) seen [seen_count++].qh = p.qh; @@ -434,7 +462,7 @@ show_periodic (struct device *dev, char *buf, size_t count, loff_t off) return count - size; } -static DEVICE_ATTR (periodic, S_IRUSR, show_periodic, NULL); +static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL); #undef DBG_SCHED_LIMIT @@ -522,7 +550,7 @@ show_registers (struct device *dev, char *buf, size_t count, loff_t off) return count - size; } -static DEVICE_ATTR (registers, S_IRUSR, show_registers, NULL); +static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL); static inline void create_debug_files (struct ehci_hcd *bus) { @@ -538,14 +566,5 @@ static inline void remove_debug_files (struct ehci_hcd *bus) device_remove_file (&bus->hcd.pdev->dev, &dev_attr_registers); } -#else /* DEBUG */ - -static inline void create_debug_files (struct ehci_hcd *bus) -{ -} - -static inline void remove_debug_files (struct ehci_hcd *bus) -{ -} +#endif /* STUB_DEBUG_FILES */ -#endif /* DEBUG */ diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 6aaf8a72f382..833de904194c 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -38,7 +38,12 @@ #endif #include <linux/usb.h> + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,32) +#include "../hcd.h" +#else #include "../core/hcd.h" +#endif #include <asm/byteorder.h> #include <asm/io.h> @@ -87,7 +92,7 @@ * 2001-June Works with usb-storage and NEC EHCI on 2.4 */ -#define DRIVER_VERSION "2002-Aug-06" +#define DRIVER_VERSION "2002-Aug-28" #define DRIVER_AUTHOR "David Brownell" #define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver" @@ -104,6 +109,8 @@ #define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ #define EHCI_TUNE_MULT_TT 1 +#define EHCI_WATCHDOG_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ + /* Initial IRQ latency: lower than default */ static int log2_irq_thresh = 0; // 0 to 6 MODULE_PARM (log2_irq_thresh, "i"); @@ -232,6 +239,19 @@ static void ehci_ready (struct ehci_hcd *ehci) static void ehci_tasklet (unsigned long param); +static void ehci_irq (struct usb_hcd *hcd); + +static void ehci_watchdog (unsigned long param) +{ + struct ehci_hcd *ehci = (struct ehci_hcd *) param; + unsigned long flags; + + /* guard against lost IAA, which wedges everything */ + spin_lock_irqsave (&ehci->lock, flags); + ehci_irq (&ehci->hcd); + spin_unlock_irqrestore (&ehci->lock, flags); +} + /* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/... * off the controller (maybe it can boot from highspeed USB disks). */ @@ -267,6 +287,7 @@ static int ehci_start (struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci (hcd); u32 temp; struct usb_device *udev; + struct usb_bus *bus; int retval; u32 hcc_params; u8 tempbyte; @@ -372,16 +393,19 @@ static int ehci_start (struct usb_hcd *hcd) ehci->tasklet.func = ehci_tasklet; ehci->tasklet.data = (unsigned long) ehci; + init_timer (&ehci->watchdog); + ehci->watchdog.function = ehci_watchdog; + ehci->watchdog.data = (unsigned long) ehci; + /* wire up the root hub */ - hcd->self.root_hub = udev = usb_alloc_dev (NULL, &hcd->self); + bus = hcd_to_bus (hcd); + bus->root_hub = udev = usb_alloc_dev (NULL, bus); if (!udev) { done2: ehci_mem_cleanup (ehci); return -ENOMEM; } - create_debug_files (ehci); - /* * Start, enabling full USB 2.0 functionality ... usb 1.1 devices * are explicitly handed to companion controller(s), so no TT is @@ -394,7 +418,7 @@ done2: /* PCI Serial Bus Release Number is at 0x60 offset */ pci_read_config_byte (hcd->pdev, 0x60, &tempbyte); temp = readw (&ehci->caps->hci_version); - info ("USB %x.%x support enabled, EHCI rev %x.%2x", + info ("USB %x.%x support enabled, EHCI rev %x.%02x", ((tempbyte & 0xf0)>>4), (tempbyte & 0x0f), temp >> 8, @@ -409,16 +433,22 @@ done2: */ usb_connect (udev); udev->speed = USB_SPEED_HIGH; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,32) + if (usb_new_device (udev) != 0) { +#else if (usb_register_root_hub (udev, &ehci->hcd.pdev->dev) != 0) { +#endif if (hcd->state == USB_STATE_RUNNING) ehci_ready (ehci); ehci_reset (ehci); - hcd->self.root_hub = 0; + bus->root_hub = 0; usb_free_dev (udev); retval = -ENODEV; goto done2; } + create_debug_files (ehci); + return 0; } @@ -428,13 +458,20 @@ static void ehci_stop (struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); - dbg ("%s: stop", hcd->self.bus_name); + dbg ("%s: stop", hcd_to_bus (hcd)->bus_name); /* no more interrupts ... */ if (hcd->state == USB_STATE_RUNNING) ehci_ready (ehci); + if (in_interrupt ()) /* should not happen!! */ + err ("stopped %s!", RUN_CONTEXT); + else + del_timer_sync (&ehci->watchdog); ehci_reset (ehci); + /* let companion controllers work when we aren't */ + writel (0, &ehci->regs->configured_flag); + remove_debug_files (ehci); /* root hub is shut down separately (first, when possible) */ @@ -463,7 +500,7 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state) int ports; int i; - dbg ("%s: suspend to %d", hcd->self.bus_name, state); + dbg ("%s: suspend to %d", hcd_to_bus (hcd)->bus_name, state); ports = HCS_N_PORTS (ehci->hcs_params); @@ -480,7 +517,7 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state) if ((temp & PORT_PE) == 0 || (temp & PORT_OWNER) != 0) continue; -dbg ("%s: suspend port %d", hcd->self.bus_name, i); +dbg ("%s: suspend port %d", hcd_to_bus (hcd)->bus_name, i); temp |= PORT_SUSPEND; writel (temp, &ehci->regs->port_status [i]); } @@ -502,7 +539,7 @@ static int ehci_resume (struct usb_hcd *hcd) int ports; int i; - dbg ("%s: resume", hcd->self.bus_name); + dbg ("%s: resume", hcd_to_bus (hcd)->bus_name); ports = HCS_N_PORTS (ehci->hcs_params); @@ -522,7 +559,7 @@ static int ehci_resume (struct usb_hcd *hcd) if ((temp & PORT_PE) == 0 || (temp & PORT_SUSPEND) != 0) continue; -dbg ("%s: resume port %d", hcd->self.bus_name, i); +dbg ("%s: resume port %d", hcd_to_bus (hcd)->bus_name, i); temp |= PORT_RESUME; writel (temp, &ehci->regs->port_status [i]); readl (&ehci->regs->command); /* unblock posted writes */ @@ -546,12 +583,17 @@ dbg ("%s: resume port %d", hcd->self.bus_name, i); static void ehci_tasklet (unsigned long param) { struct ehci_hcd *ehci = (struct ehci_hcd *) param; + unsigned long flags; + + spin_lock_irqsave (&ehci->lock, flags); if (ehci->reclaim_ready) - end_unlink_async (ehci); - scan_async (ehci); + flags = end_unlink_async (ehci, flags); + flags = scan_async (ehci, flags); if (ehci->next_uframe != -1) - scan_periodic (ehci); + flags = scan_periodic (ehci, flags); + + spin_unlock_irqrestore (&ehci->lock, flags); } /*-------------------------------------------------------------------------*/ @@ -564,7 +606,7 @@ static void ehci_irq (struct usb_hcd *hcd) /* e.g. cardbus physical eject */ if (status == ~(u32) 0) { - dbg ("%s: device removed!", hcd->self.bus_name); + dbg ("%s: device removed!", hcd_to_bus (hcd)->bus_name); goto dead; } @@ -597,7 +639,7 @@ static void ehci_irq (struct usb_hcd *hcd) /* PCI errors [4.15.2.4] */ if (unlikely ((status & STS_FATAL) != 0)) { err ("%s: fatal error, state %x", - hcd->self.bus_name, hcd->state); + hcd_to_bus (hcd)->bus_name, hcd->state); dead: ehci_reset (ehci); /* generic layer kills/unlinks all urbs, then @@ -673,7 +715,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) unsigned long flags; dbg ("%s urb_dequeue %p qh %p state %d", - hcd->self.bus_name, urb, qh, qh->qh_state); + hcd_to_bus (hcd)->bus_name, urb, qh, qh->qh_state); switch (usb_pipetype (urb->pipe)) { // case PIPE_CONTROL: @@ -681,7 +723,13 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) default: spin_lock_irqsave (&ehci->lock, flags); if (ehci->reclaim) { - dbg ("dq: reclaim busy, %s", RUN_CONTEXT); + dbg ("dq %p: reclaim = %p, %s", + qh, ehci->reclaim, RUN_CONTEXT); + if (qh == ehci->reclaim) { + /* unlinking qh for another queued urb? */ + spin_unlock_irqrestore (&ehci->lock, flags); + return 0; + } if (in_interrupt ()) { spin_unlock_irqrestore (&ehci->lock, flags); return -EAGAIN; @@ -702,19 +750,19 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) break; case PIPE_INTERRUPT: + spin_lock_irqsave (&ehci->lock, flags); if (qh->qh_state == QH_STATE_LINKED) { /* messy, can spin or block a microframe ... */ - intr_deschedule (ehci, qh, 1); + flags = intr_deschedule (ehci, qh, 1, flags); /* qh_state == IDLE */ } - qh_completions (ehci, qh); + flags = qh_completions (ehci, qh, flags); /* reschedule QH iff another request is queued */ if (!list_empty (&qh->qtd_list) && HCD_IS_RUNNING (ehci->hcd.state)) { int status; - spin_lock_irqsave (&ehci->lock, flags); status = qh_schedule (ehci, qh); spin_unlock_irqrestore (&ehci->lock, flags); @@ -726,7 +774,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) } return status; } - + spin_unlock_irqrestore (&ehci->lock, flags); break; case PIPE_ISOCHRONOUS: @@ -754,7 +802,8 @@ static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev) /* ASSERT: no requests/urbs are still linked (so no TDs) */ /* ASSERT: nobody can be submitting urbs for this any more */ - dbg ("%s: free_config devnum %d", hcd->self.bus_name, udev->devnum); + dbg ("%s: free_config devnum %d", + hcd_to_bus (hcd)->bus_name, udev->devnum); spin_lock_irqsave (&ehci->lock, flags); for (i = 0; i < 32; i++) { @@ -775,7 +824,8 @@ static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev) why = 0; if (why) { err ("dev %s-%s ep %d-%s error: %s", - hcd->self.bus_name, udev->devpath, + hcd_to_bus (hcd)->bus_name, + udev->devpath, i & 0xf, (i & 0x10) ? "IN" : "OUT", why); BUG (); @@ -805,8 +855,7 @@ static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev) start_unlink_async (ehci, qh); while (qh->qh_state != QH_STATE_IDLE && ehci->hcd.state != USB_STATE_HALT) { - spin_unlock_irqrestore (&ehci->lock, - flags); + spin_unlock_irqrestore (&ehci->lock, flags); wait_ms (1); spin_lock_irqsave (&ehci->lock, flags); } diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 22d4919cbf97..a0cc9d50b2ff 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -41,14 +41,17 @@ static int check_reset_complete ( /* if reset finished and it's still not enabled -- handoff */ if (!(port_status & PORT_PE)) { dbg ("%s port %d full speed, give to companion, 0x%x", - ehci->hcd.self.bus_name, index + 1, port_status); + hcd_to_bus (&ehci->hcd)->bus_name, + index + 1, port_status); // what happens if HCS_N_CC(params) == 0 ? port_status |= PORT_OWNER; writel (port_status, &ehci->regs->port_status [index]); } else - dbg ("%s port %d high speed", ehci->hcd.self.bus_name, index + 1); + dbg ("%s port %d high speed", + hcd_to_bus (&ehci->hcd)->bus_name, + index + 1); return port_status; } @@ -310,11 +313,13 @@ static int ehci_hub_control ( if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT && PORT_USB11 (temp)) { dbg ("%s port %d low speed, give to companion", - hcd->self.bus_name, wIndex + 1); + hcd_to_bus (&ehci->hcd)->bus_name, + wIndex + 1); temp |= PORT_OWNER; } else { vdbg ("%s port %d reset", - hcd->self.bus_name, wIndex + 1); + hcd_to_bus (&ehci->hcd)->bus_name, + wIndex + 1); temp |= PORT_RESET; temp &= ~PORT_PE; diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 7c401d7d2c60..157e2306e793 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -161,9 +161,10 @@ static inline void qtd_copy_status (struct urb *urb, size_t length, u32 token) /* urb->lock ignored from here on (hcd is done with urb) */ -static void ehci_urb_done ( +static unsigned long ehci_urb_done ( struct ehci_hcd *ehci, - struct urb *urb + struct urb *urb, + unsigned long flags ) { #ifdef INTR_AUTOMAGIC struct urb *resubmit = 0; @@ -177,7 +178,7 @@ static void ehci_urb_done ( if ((qh->hw_info2 & cpu_to_le32 (0x00ff)) != 0) { /* ... update hc-wide periodic stats (for usbfs) */ - ehci->hcd.self.bandwidth_int_reqs--; + hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs--; #ifdef INTR_AUTOMAGIC if (!((urb->status == -ENOENT) @@ -199,6 +200,8 @@ static void ehci_urb_done ( urb->status = 0; } + /* complete() can reenter this HCD */ + spin_unlock_irqrestore (&ehci->lock, flags); usb_hcd_giveback_urb (&ehci->hcd, urb); #ifdef INTR_AUTOMAGIC @@ -212,34 +215,32 @@ static void ehci_urb_done ( int status; resubmit->dev = dev; - status = usb_submit_urb (resubmit, SLAB_KERNEL); + status = SUBMIT_URB (resubmit, SLAB_KERNEL); if (status != 0) err ("can't resubmit interrupt urb %p: status %d", resubmit, status); usb_put_urb (resubmit); } #endif + + spin_lock_irqsave (&ehci->lock, flags); + return flags; } /* - * Process completed qtds for a qh, issuing completions if needed. - * Frees qtds, unmaps buf, returns URB to driver. - * Races up to qh->hw_current; returns number of urb completions. + * Process and free completed qtds for a qh, returning URBs to drivers. + * Chases up to qh->hw_current, returns irqsave flags (maybe modified). */ -static void -qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) +static unsigned long +qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, unsigned long flags) { struct ehci_qtd *qtd, *last; struct list_head *next, *qtd_list = &qh->qtd_list; int unlink = 0, halted = 0; - unsigned long flags; - spin_lock_irqsave (&ehci->lock, flags); - if (unlikely (list_empty (qtd_list))) { - spin_unlock_irqrestore (&ehci->lock, flags); - return; - } + if (unlikely (list_empty (qtd_list))) + return flags; /* scan QTDs till end of list, or we reach an active one */ for (qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list), @@ -252,12 +253,8 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) /* clean up any state from previous QTD ...*/ if (last) { - if (likely (last->urb != urb)) { - /* complete() can reenter this HCD */ - spin_unlock_irqrestore (&ehci->lock, flags); - ehci_urb_done (ehci, last->urb); - spin_lock_irqsave (&ehci->lock, flags); - } + if (likely (last->urb != urb)) + flags = ehci_urb_done (ehci, last->urb, flags); /* qh overlays can have HC's old cached copies of * next qtd ptrs, if an URB was queued afterwards. @@ -283,6 +280,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) || (ehci->hcd.state == USB_STATE_HALT) || (qh->qh_state == QH_STATE_IDLE); + // FIXME Remove the automagic unlink mode. + // Drivers can now clean up safely; its' their job. + /* fault: unlink the rest, since this qtd saw an error? */ if (unlikely ((token & QTD_STS_HALT) != 0)) { unlink = 1; @@ -341,18 +341,19 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) #endif } - /* patch up list head? */ + /* last urb's completion might still need calling */ + if (likely (last != 0)) { + flags = ehci_urb_done (ehci, last->urb, flags); + ehci_qtd_free (ehci, last); + } + + /* reactivate queue after error and driver's cleanup */ if (unlikely (halted && !list_empty (qtd_list))) { qh_update (qh, list_entry (qtd_list->next, struct ehci_qtd, qtd_list)); } - spin_unlock_irqrestore (&ehci->lock, flags); - /* last urb's completion might still need calling */ - if (likely (last != 0)) { - ehci_urb_done (ehci, last->urb); - ehci_qtd_free (ehci, last); - } + return flags; } /*-------------------------------------------------------------------------*/ @@ -367,31 +368,12 @@ static void qtd_list_free ( struct list_head *qtd_list ) { struct list_head *entry, *temp; - int unmapped = 0; list_for_each_safe (entry, temp, qtd_list) { struct ehci_qtd *qtd; qtd = list_entry (entry, struct ehci_qtd, qtd_list); list_del (&qtd->qtd_list); - if (unmapped != 2) { - int direction; - size_t size; - - /* for ctrl unmap twice: SETUP and DATA; - * else (bulk, intr) just once: DATA - */ - if (!unmapped++ && usb_pipecontrol (urb->pipe)) { - direction = PCI_DMA_TODEVICE; - size = sizeof (struct usb_ctrlrequest); - } else { - direction = usb_pipein (urb->pipe) - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE; - size = qtd->urb->transfer_buffer_length; - unmapped++; - } - } ehci_qtd_free (ehci, qtd); } } @@ -670,8 +652,8 @@ ehci_qh_make ( info2 |= hb_mult (maxp) << 30; } break; -#ifdef DEBUG default: +#ifdef DEBUG BUG (); #endif } @@ -859,7 +841,8 @@ submit_async ( epnum |= 0x10; vdbg ("%s: submit_async urb %p len %d ep %d-%s qtd %p [qh %p]", - ehci->hcd.self.bus_name, urb, urb->transfer_buffer_length, + hcd_to_bus (&ehci->hcd)->bus_name, + urb, urb->transfer_buffer_length, epnum & 0x0f, (epnum & 0x10) ? "in" : "out", qtd, dev ? dev->ep [epnum] : (void *)~0); @@ -886,25 +869,28 @@ submit_async ( /* the async qh for the qtds being reclaimed are now unlinked from the HC */ /* caller must not own ehci->lock */ -static void end_unlink_async (struct ehci_hcd *ehci) +static unsigned long +end_unlink_async (struct ehci_hcd *ehci, unsigned long flags) { struct ehci_qh *qh = ehci->reclaim; + del_timer (&ehci->watchdog); + qh->qh_state = QH_STATE_IDLE; qh->qh_next.qh = 0; qh_put (ehci, qh); // refcount from reclaim ehci->reclaim = 0; ehci->reclaim_ready = 0; - qh_completions (ehci, qh); + flags = qh_completions (ehci, qh, flags); - // unlink any urb should now unlink all following urbs, so that - // relinking only happens for urbs before the unlinked ones. if (!list_empty (&qh->qtd_list) && HCD_IS_RUNNING (ehci->hcd.state)) qh_link_async (ehci, qh); else qh_put (ehci, qh); // refcount from async list + + return flags; } @@ -975,16 +961,17 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) cmd |= CMD_IAAD; writel (cmd, &ehci->regs->command); /* posted write need not be known to HC yet ... */ + + mod_timer (&ehci->watchdog, jiffies + EHCI_WATCHDOG_JIFFIES); } /*-------------------------------------------------------------------------*/ -static void scan_async (struct ehci_hcd *ehci) +static unsigned long +scan_async (struct ehci_hcd *ehci, unsigned long flags) { struct ehci_qh *qh; - unsigned long flags; - spin_lock_irqsave (&ehci->lock, flags); rescan: qh = ehci->async; if (likely (qh != 0)) { @@ -993,12 +980,9 @@ rescan: if (!list_empty (&qh->qtd_list)) { // dbg_qh ("scan_async", ehci, qh); qh = qh_get (qh); - spin_unlock_irqrestore (&ehci->lock, flags); /* concurrent unlink could happen here */ - qh_completions (ehci, qh); - - spin_lock_irqsave (&ehci->lock, flags); + flags = qh_completions (ehci, qh, flags); qh_put (ehci, qh); } @@ -1020,6 +1004,5 @@ rescan: goto rescan; } while (qh != ehci->async); } - - spin_unlock_irqrestore (&ehci->lock, flags); + return flags; } diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index e11edf8307fc..2802fa125663 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -222,17 +222,15 @@ static int disable_periodic (struct ehci_hcd *ehci) // FIXME microframe periods not yet handled -static void intr_deschedule ( +static unsigned long intr_deschedule ( struct ehci_hcd *ehci, struct ehci_qh *qh, - int wait + int wait, + unsigned long flags ) { - unsigned long flags; int status; unsigned frame = qh->start; - spin_lock_irqsave (&ehci->lock, flags); - do { periodic_unlink (ehci, frame, qh); qh_put (ehci, qh); @@ -251,8 +249,6 @@ static void intr_deschedule ( vdbg ("periodic schedule still enabled"); } - spin_unlock_irqrestore (&ehci->lock, flags); - /* * If the hc may be looking at this qh, then delay a uframe * (yeech!) to be sure it's done. @@ -260,8 +256,10 @@ static void intr_deschedule ( */ if (((ehci_get_frame (&ehci->hcd) - frame) % qh->period) == 0) { if (wait) { + spin_unlock_irqrestore (&ehci->lock, flags); udelay (125); qh->hw_next = EHCI_LIST_END; + spin_lock_irqsave (&ehci->lock, flags); } else { /* we may not be IDLE yet, but if the qh is empty * the race is very short. then if qh also isn't @@ -275,12 +273,13 @@ static void intr_deschedule ( qh->qh_state = QH_STATE_IDLE; /* update per-qh bandwidth utilization (for usbfs) */ - ehci->hcd.self.bandwidth_allocated -= + hcd_to_bus (&ehci->hcd)->bandwidth_allocated -= (qh->usecs + qh->c_usecs) / qh->period; vdbg ("descheduled qh %p, per = %d frame = %d count = %d, urbs = %d", qh, qh->period, frame, atomic_read (&qh->refcount), ehci->periodic_sched); + return flags; } static int check_period ( @@ -436,7 +435,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) } while (frame < ehci->periodic_size); /* update per-qh bandwidth for usbfs */ - ehci->hcd.self.bandwidth_allocated += + hcd_to_bus (&ehci->hcd)->bandwidth_allocated += (qh->usecs + qh->c_usecs) / qh->period; /* maybe enable periodic schedule processing */ @@ -486,7 +485,7 @@ static int intr_submit ( BUG_ON (qh == 0); /* ... update usbfs periodic stats */ - ehci->hcd.self.bandwidth_int_reqs++; + hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs++; done: spin_unlock_irqrestore (&ehci->lock, flags); @@ -513,12 +512,10 @@ intr_complete ( } /* handle any completions */ - spin_unlock_irqrestore (&ehci->lock, flags); - qh_completions (ehci, qh); - spin_lock_irqsave (&ehci->lock, flags); + flags = qh_completions (ehci, qh, flags); if (unlikely (list_empty (&qh->qtd_list))) - intr_deschedule (ehci, qh, 0); + flags = intr_deschedule (ehci, qh, 0, flags); return flags; } @@ -1091,13 +1088,12 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags) /*-------------------------------------------------------------------------*/ -static void scan_periodic (struct ehci_hcd *ehci) +static unsigned long +scan_periodic (struct ehci_hcd *ehci, unsigned long flags) { unsigned frame, clock, now_uframe, mod; - unsigned long flags; mod = ehci->periodic_size << 3; - spin_lock_irqsave (&ehci->lock, flags); /* * When running, scan from last scan point up to "now" @@ -1237,5 +1233,5 @@ restart: } else frame = (frame + 1) % ehci->periodic_size; } - spin_unlock_irqrestore (&ehci->lock, flags); + return flags; } diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 45af6f3c7726..76cddfd04f27 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -69,6 +69,8 @@ struct ehci_hcd { /* one per controller */ struct pci_pool *qtd_pool; /* one or more per qh */ struct pci_pool *itd_pool; /* itd per iso urb */ struct pci_pool *sitd_pool; /* sitd per split iso urb */ + + struct timer_list watchdog; }; /* unwrap an HCD pointer to get an EHCI_HCD pointer */ @@ -389,4 +391,26 @@ struct ehci_fstn { union ehci_shadow fstn_next; /* ptr to periodic q entry */ } __attribute__ ((aligned (32))); +/*-------------------------------------------------------------------------*/ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,32) + +#define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb) +#define STUB_DEBUG_FILES + +#else /* LINUX_VERSION_CODE */ + +static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd) + { return &hcd->self; } + +#define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb,mem_flags) + +#ifndef DEBUG +#define STUB_DEBUG_FILES +#endif /* DEBUG */ + +#endif /* LINUX_VERSION_CODE */ + +/*-------------------------------------------------------------------------*/ + #endif /* __LINUX_EHCI_HCD_H */ diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 4545a999df90..b338d3a6328a 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -72,37 +72,6 @@ static void urb_print (struct urb * urb, char * str, int small) #endif } -static inline struct ed * -dma_to_ed (struct ohci_hcd *hc, dma_addr_t ed_dma); - -/* print non-empty branches of the periodic ed tree */ -static void __attribute__ ((unused)) -ohci_dump_periodic (struct ohci_hcd *ohci, char *label) -{ - int i, j; - u32 *ed_p; - int printed = 0; - - for (i= 0; i < 32; i++) { - j = 5; - ed_p = &(ohci->hcca->int_table [i]); - if (*ed_p == 0) - continue; - printed = 1; - printk (KERN_DEBUG "%s, ohci %s frame %2d:", - label, ohci->hcd.self.bus_name, i); - while (*ed_p != 0 && j--) { - struct ed *ed = dma_to_ed (ohci, le32_to_cpup(ed_p)); - printk (" %p/%08x;", ed, ed->hwINFO); - ed_p = &ed->hwNextED; - } - printk ("\n"); - } - if (!printed) - printk (KERN_DEBUG "%s, ohci %s, empty periodic schedule\n", - label, ohci->hcd.self.bus_name); -} - static void ohci_dump_intr_mask (char *label, __u32 mask) { dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s", @@ -239,7 +208,8 @@ static void ohci_dump (struct ohci_hcd *controller, int verbose) if (verbose) ohci_dump_periodic (controller, "hcca"); #endif - dbg ("hcca frame #%04x", controller->hcca->frame_no); + if (controller->hcca) + dbg ("hcca frame #%04x", controller->hcca->frame_no); ohci_dump_roothub (controller, 1); } @@ -316,8 +286,9 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose) case ED_IN: type = "-IN"; break; /* else from TDs ... control */ } - dbg (" info %08x MAX=%d%s%s%s EP=%d%s DEV=%d", le32_to_cpu (tmp), - 0x0fff & (le32_to_cpu (tmp) >> 16), + dbg (" info %08x MAX=%d%s%s%s%s EP=%d%s DEV=%d", le32_to_cpu (tmp), + 0x03ff & (le32_to_cpu (tmp) >> 16), + (tmp & ED_DEQUEUE) ? " DQ" : "", (tmp & ED_ISO) ? " ISO" : "", (tmp & ED_SKIP) ? " SKIP" : "", (tmp & ED_LOWSPEED) ? " LOW" : "", @@ -344,5 +315,222 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose) } } +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,32) +# define DRIVERFS_DEBUG_FILES #endif +#endif /* DEBUG */ + +/*-------------------------------------------------------------------------*/ + +#ifdef DRIVERFS_DEBUG_FILES + +static ssize_t +show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) +{ + unsigned temp, size = count; + + if (!ed) + return 0; + + /* print first --> last */ + while (ed->ed_prev) + ed = ed->ed_prev; + + /* dump a snapshot of the bulk or control schedule */ + while (ed) { + u32 info = ed->hwINFO; + u32 scratch = cpu_to_le32p (&ed->hwINFO); + struct list_head *entry; + struct td *td; + + temp = snprintf (buf, size, + "ed/%p %cs dev%d ep%d-%s max %d %08x%s%s %s", + ed, + (info & ED_LOWSPEED) ? 'l' : 'f', + scratch & 0x7f, + (scratch >> 7) & 0xf, + (info & ED_IN) ? "in" : "out", + 0x03ff & (scratch >> 16), + scratch, + (info & ED_SKIP) ? " s" : "", + (ed->hwHeadP & ED_H) ? " H" : "", + (ed->hwHeadP & ED_C) ? data1 : data0); + size -= temp; + buf += temp; + + list_for_each (entry, &ed->td_list) { + u32 cbp, be; + + td = list_entry (entry, struct td, td_list); + scratch = cpu_to_le32p (&td->hwINFO); + cbp = le32_to_cpup (&td->hwCBP); + be = le32_to_cpup (&td->hwBE); + temp = snprintf (buf, size, + "\n\ttd %p %s %d cc=%x urb %p (%08x)", + td, + ({ char *pid; + switch (scratch & TD_DP) { + case TD_DP_SETUP: pid = "setup"; break; + case TD_DP_IN: pid = "in"; break; + case TD_DP_OUT: pid = "out"; break; + default: pid = "(?)"; break; + } pid;}), + cbp ? (be + 1 - cbp) : 0, + TD_CC_GET (scratch), td->urb, scratch); + size -= temp; + buf += temp; + } + + temp = snprintf (buf, size, "\n"); + size -= temp; + buf += temp; + + ed = ed->ed_next; + } + return count - size; +} + +static ssize_t +show_async (struct device *dev, char *buf, size_t count, loff_t off) +{ + struct pci_dev *pdev; + struct ohci_hcd *ohci; + size_t temp; + unsigned long flags; + + if (off != 0) + return 0; + pdev = container_of (dev, struct pci_dev, dev); + ohci = container_of (pci_get_drvdata (pdev), struct ohci_hcd, hcd); + + /* display control and bulk lists together, for simplicity */ + spin_lock_irqsave (&ohci->lock, flags); + temp = show_list (ohci, buf, count, ohci->ed_controltail); + count = show_list (ohci, buf + temp, count - temp, ohci->ed_bulktail); + spin_unlock_irqrestore (&ohci->lock, flags); + + return temp + count; +} +static DEVICE_ATTR (async, S_IRUGO, show_async, NULL); + + +#define DBG_SCHED_LIMIT 64 + +static ssize_t +show_periodic (struct device *dev, char *buf, size_t count, loff_t off) +{ + struct pci_dev *pdev; + struct ohci_hcd *ohci; + struct ed **seen, *ed; + unsigned long flags; + unsigned temp, size, seen_count; + char *next; + unsigned i; + + if (off != 0) + return 0; + if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC))) + return 0; + seen_count = 0; + + pdev = container_of (dev, struct pci_dev, dev); + ohci = container_of (pci_get_drvdata (pdev), struct ohci_hcd, hcd); + next = buf; + size = count; + + temp = snprintf (next, size, "size = %d\n", NUM_INTS); + size -= temp; + next += temp; + + /* dump a snapshot of the periodic schedule (and load) */ + spin_lock_irqsave (&ohci->lock, flags); + for (i = 0; i < NUM_INTS; i++) { + if (!(ed = ohci->periodic [i])) + continue; + + temp = snprintf (next, size, "%2d [%3d]:", i, ohci->load [i]); + size -= temp; + next += temp; + + do { + temp = snprintf (next, size, " ed%d/%p", + ed->interval, ed); + size -= temp; + next += temp; + for (temp = 0; temp < seen_count; temp++) { + if (seen [temp] == ed) + break; + } + + /* show more info the first time around */ + if (temp == seen_count) { + u32 info = ed->hwINFO; + u32 scratch = cpu_to_le32p (&ed->hwINFO); + + temp = snprintf (next, size, + " (%cs dev%d%s ep%d-%s" + " max %d %08x%s%s)", + (info & ED_LOWSPEED) ? 'l' : 'f', + scratch & 0x7f, + (info & ED_ISO) ? " iso" : "", + (scratch >> 7) & 0xf, + (info & ED_IN) ? "in" : "out", + 0x03ff & (scratch >> 16), + scratch, + (info & ED_SKIP) ? " s" : "", + (ed->hwHeadP & ED_H) ? " H" : ""); + size -= temp; + next += temp; + + // FIXME some TD info too + + if (seen_count < DBG_SCHED_LIMIT) + seen [seen_count++] = ed; + + ed = ed->ed_next; + + } else { + /* we've seen it and what's after */ + temp = 0; + ed = 0; + } + + } while (ed); + + temp = snprintf (next, size, "\n"); + size -= temp; + next += temp; + } + spin_unlock_irqrestore (&ohci->lock, flags); + kfree (seen); + + return count - size; +} +static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL); + +#undef DBG_SCHED_LIMIT + +static inline void create_debug_files (struct ohci_hcd *bus) +{ + device_create_file (&bus->hcd.pdev->dev, &dev_attr_async); + device_create_file (&bus->hcd.pdev->dev, &dev_attr_periodic); + // registers + dbg ("%s: created debug files", bus->hcd.self.bus_name); +} + +static inline void remove_debug_files (struct ohci_hcd *bus) +{ + device_remove_file (&bus->hcd.pdev->dev, &dev_attr_async); + device_remove_file (&bus->hcd.pdev->dev, &dev_attr_periodic); +} + +#else /* empty stubs for creating those files */ + +static inline void create_debug_files (struct ohci_hcd *bus) { } +static inline void remove_debug_files (struct ohci_hcd *bus) { } + +#endif /* DRIVERFS_DEBUG_FILES */ + +/*-------------------------------------------------------------------------*/ + diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index d7cc8c544068..f8f5d5757987 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -17,6 +17,8 @@ * * History: * + * 2002/09/03 get rid of ed hashtables, rework periodic scheduling and + * bandwidth accounting; if debugging, show schedules in driverfs * 2002/07/19 fixes to management of ED and schedule state. * 2002/06/09 SA-1111 support (Christopher Hoover) * 2002/06/01 remember frame when HC won't see EDs any more; use that info @@ -66,7 +68,6 @@ * v1.0 1999/04/27 initial release * * This file is licenced under the GPL. - * $Id: ohci-hcd.c,v 1.9 2002/03/27 20:41:57 dbrownell Exp $ */ #include <linux/config.h> @@ -107,8 +108,8 @@ * - lots more testing!! */ -#define DRIVER_VERSION "2002-Jul-19" -#define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell" +#define DRIVER_VERSION "2002-Sep-03" +#define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" /*-------------------------------------------------------------------------*/ @@ -152,7 +153,6 @@ static int ohci_urb_enqueue ( unsigned int pipe = urb->pipe; int i, size = 0; unsigned long flags; - int bustime = 0; int retval = 0; #ifdef OHCI_VERBOSE_DEBUG @@ -230,43 +230,32 @@ static int ohci_urb_enqueue ( } } -// FIXME: much of this switch should be generic, move to hcd code ... -// ... and what's not generic can't really be handled this way. -// need to consider periodicity for both types! - - /* allocate and claim bandwidth if needed; ISO - * needs start frame index if it was't provided. - */ - switch (usb_pipetype (pipe)) { - case PIPE_ISOCHRONOUS: - if (urb->transfer_flags & USB_ISO_ASAP) { - urb->start_frame = ((ed->state != ED_IDLE) - ? (ed->intriso.last_iso + 1) - : (le16_to_cpu (ohci->hcca->frame_no) - + 10)) & 0xffff; - } - /* FALLTHROUGH */ - case PIPE_INTERRUPT: - if (urb->bandwidth == 0) { - bustime = usb_check_bandwidth (urb->dev, urb); - } - if (bustime < 0) { - retval = bustime; - goto fail; - } - usb_claim_bandwidth (urb->dev, urb, - bustime, usb_pipeisoc (urb->pipe)); - } + /* schedule the ed if needed */ + if (ed->state == ED_IDLE) { + retval = ed_schedule (ohci, ed); + if (retval < 0) + goto fail; + if (ed->type == PIPE_ISOCHRONOUS) { + u16 frame = le16_to_cpu (ohci->hcca->frame_no); - urb->hcpriv = urb_priv; + /* delay a few frames before the first TD */ + frame += max_t (u16, 8, ed->interval); + frame &= ~(ed->interval - 1); + frame |= ed->branch; + urb->start_frame = frame; - /* schedule the ed if needed */ - if (ed->state == ED_IDLE) - ed_schedule (ohci, ed); + /* yes, only USB_ISO_ASAP is supported, and + * urb->start_frame is never used as input. + */ + } + } else if (ed->type == PIPE_ISOCHRONOUS) + urb->start_frame = ed->last_iso + ed->interval; /* fill the TDs and link them to the ed; and * enable that part of the schedule, if needed + * and update count of queued periodic urbs */ + urb->hcpriv = urb_priv; td_submit_urb (ohci, urb); fail: @@ -530,13 +519,15 @@ static int hc_start (struct ohci_hcd *ohci) usb_connect (udev); udev->speed = USB_SPEED_FULL; if (usb_register_root_hub (udev, ohci->parent_dev) != 0) { - usb_free_dev (udev); + usb_free_dev (udev); + ohci->hcd.self.root_hub = NULL; disable (ohci); ohci->hc_control &= ~OHCI_CTRL_HCFS; writel (ohci->hc_control, &ohci->regs->control); return -ENODEV; } + create_debug_files (ohci); return 0; } @@ -571,7 +562,8 @@ static void ohci_irq (struct usb_hcd *hcd) if (ints & OHCI_INTR_UE) { disable (ohci); - err ("OHCI Unrecoverable Error, %s disabled", hcd->self.bus_name); + err ("OHCI Unrecoverable Error, %s disabled", + hcd->self.bus_name); // e.g. due to PCI Master/Target Abort #ifdef DEBUG @@ -620,10 +612,14 @@ static void ohci_stop (struct usb_hcd *hcd) if (!ohci->disabled) hc_reset (ohci); + remove_debug_files (ohci); ohci_mem_cleanup (ohci); - - pci_free_consistent (ohci->hcd.pdev, sizeof *ohci->hcca, - ohci->hcca, ohci->hcca_dma); + if (ohci->hcca) { + pci_free_consistent (ohci->hcd.pdev, sizeof *ohci->hcca, + ohci->hcca, ohci->hcca_dma); + ohci->hcca = NULL; + ohci->hcca_dma = 0; + } } /*-------------------------------------------------------------------------*/ @@ -646,14 +642,13 @@ static int hc_restart (struct ohci_hcd *ohci) usb_disconnect (&ohci->hcd.self.root_hub); /* empty the interrupt branches */ - for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load [i] = 0; + for (i = 0; i < NUM_INTS; i++) ohci->load [i] = 0; for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0; /* no EDs to remove */ ohci->ed_rm_list = NULL; /* empty control and bulk lists */ - ohci->ed_isotail = NULL; ohci->ed_controltail = NULL; ohci->ed_bulktail = NULL; diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c index c2b0b2ac8be9..51322551606b 100644 --- a/drivers/usb/host/ohci-mem.c +++ b/drivers/usb/host/ohci-mem.c @@ -5,7 +5,6 @@ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> * * This file is licenced under the GPL. - * $Id: ohci-mem.c,v 1.3 2002/03/22 16:04:54 dbrownell Exp $ */ /*-------------------------------------------------------------------------*/ @@ -52,13 +51,6 @@ dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma) return scan->virt; } -static struct ed * -dma_to_ed (struct ohci_hcd *hc, dma_addr_t ed_dma) -{ - return (struct ed *) dma_to_ed_td(&(hc->ed_hash [ED_HASH_FUNC(ed_dma)]), - ed_dma); -} - static struct td * dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma) { @@ -98,13 +90,6 @@ hash_add_ed_td ( } static inline int -hash_add_ed (struct ohci_hcd *hc, struct ed *ed, int mem_flags) -{ - return hash_add_ed_td (&(hc->ed_hash [ED_HASH_FUNC (ed->dma)]), - ed, ed->dma, mem_flags); -} - -static inline int hash_add_td (struct ohci_hcd *hc, struct td *td, int mem_flags) { return hash_add_ed_td (&(hc->td_hash [TD_HASH_FUNC (td->td_dma)]), @@ -139,12 +124,6 @@ hash_free_ed_td (struct hash_list_t *entry, void *virt) } static inline void -hash_free_ed (struct ohci_hcd *hc, struct ed * ed) -{ - hash_free_ed_td (&(hc->ed_hash[ED_HASH_FUNC(ed->dma)]), ed); -} - -static inline void hash_free_td (struct ohci_hcd *hc, struct td * td) { hash_free_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), td); @@ -223,11 +202,6 @@ ed_alloc (struct ohci_hcd *hc, int mem_flags) memset (ed, 0, sizeof (*ed)); INIT_LIST_HEAD (&ed->td_list); ed->dma = dma; - /* hash it for later reverse mapping */ - if (!hash_add_ed (hc, ed, mem_flags)) { - pci_pool_free (hc->ed_cache, ed, dma); - return NULL; - } } return ed; } @@ -235,7 +209,6 @@ ed_alloc (struct ohci_hcd *hc, int mem_flags) static void ed_free (struct ohci_hcd *hc, struct ed *ed) { - hash_free_ed (hc, ed); pci_pool_free (hc->ed_cache, ed, ed->dma); } diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index fd3c2680f9eb..f4ab56e84030 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -5,7 +5,6 @@ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> * * This file is licenced under the GPL. - * $Id: ohci-q.c,v 1.8 2002/03/27 20:57:01 dbrownell Exp $ */ static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv) @@ -52,6 +51,15 @@ static void finish_urb (struct ohci_hcd *ohci, struct urb *urb) urb->status = 0; spin_unlock_irqrestore (&urb->lock, flags); + switch (usb_pipetype (urb->pipe)) { + case PIPE_ISOCHRONOUS: + ohci->hcd.self.bandwidth_isoc_reqs--; + break; + case PIPE_INTERRUPT: + ohci->hcd.self.bandwidth_int_reqs--; + break; + } + #ifdef OHCI_VERBOSE_DEBUG urb_print (urb, "RET", usb_pipeout (urb->pipe)); #endif @@ -111,67 +119,111 @@ static inline void intr_resub (struct ohci_hcd *hc, struct urb *urb) * ED handling functions *-------------------------------------------------------------------------*/ -/* search for the right branch to insert an interrupt ed into the int tree - * do some load balancing; - * returns the branch - * FIXME allow for failure, when there's no bandwidth left; - * and consider iso loads too +/* search for the right schedule branch to use for a periodic ed. + * does some load balancing; returns the branch, or negative errno. */ -static int ep_int_balance (struct ohci_hcd *ohci, int interval, int load) +static int balance (struct ohci_hcd *ohci, int interval, int load) { - int i, branch = 0; - - /* search for the least loaded interrupt endpoint branch */ - for (i = 0; i < NUM_INTS ; i++) - if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i]) - branch = i; + int i, branch = -ENOSPC; - branch = branch % interval; - for (i = branch; i < NUM_INTS; i += interval) - ohci->ohci_int_load [i] += load; + /* iso periods can be huge; iso tds specify frame numbers */ + if (interval > NUM_INTS) + interval = NUM_INTS; + /* search for the least loaded schedule branch of that period + * that has enough bandwidth left unreserved. + */ + for (i = 0; i < interval ; i++) { + if (branch < 0 || ohci->load [branch] > ohci->load [i]) { +#ifdef CONFIG_USB_BANDWIDTH + int j; + + /* usb 1.1 says 90% of one frame */ + for (j = i; j < NUM_INTS; j += interval) { + if ((ohci->load [j] + load) > 900) + break; + } + if (j < NUM_INTS) + continue; +#endif + branch = i; + } + } return branch; } /*-------------------------------------------------------------------------*/ -/* the int tree is a binary tree - * in order to process it sequentially the indexes of the branches have - * to be mapped the mapping reverses the bits of a word of num_bits length +/* both iso and interrupt requests have periods; this routine puts them + * into the schedule tree in the apppropriate place. most iso devices use + * 1msec periods, but that's not required. */ -static int ep_rev (int num_bits, int word) +static void periodic_link (struct ohci_hcd *ohci, struct ed *ed) { - int i, wout = 0; + unsigned i; - for (i = 0; i < num_bits; i++) - wout |= (( (word >> i) & 1) << (num_bits - i - 1)); - return wout; -} + dbg ("%s: link %sed %p branch %d [%dus.], interval %d", + ohci->hcd.self.bus_name, + (ed->hwINFO & ED_ISO) ? "iso " : "", + ed, ed->branch, ed->load, ed->interval); -/*-------------------------------------------------------------------------*/ + for (i = ed->branch; i < NUM_INTS; i += ed->interval) { + struct ed **prev = &ohci->periodic [i]; + u32 *prev_p = &ohci->hcca->int_table [i]; + struct ed *here = *prev; + + /* sorting each branch by period (slow before fast) + * lets us share the faster parts of the tree. + * (plus maybe: put interrupt eds before iso) + */ + while (here && ed != here) { + if (ed->interval > here->interval) + break; + prev = &here->ed_next; + prev_p = &here->hwNextED; + here = *prev; + } + if (ed != here) { + ed->ed_next = here; + if (here) + ed->hwNextED = *prev_p; + wmb (); + *prev = ed; + *prev_p = cpu_to_le32p (&ed->dma); + } + ohci->load [i] += ed->load; + } + ohci->hcd.self.bandwidth_allocated += ed->load / ed->interval; +} /* link an ed into one of the HC chains */ -static void ed_schedule (struct ohci_hcd *ohci, struct ed *ed) +static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) { - int int_branch, i; - int inter, interval, load; - __u32 *ed_p; + int branch; ed->state = ED_OPER; + ed->ed_prev = 0; + ed->ed_next = 0; ed->hwNextED = 0; wmb (); /* we care about rm_list when setting CLE/BLE in case the HC was at * work on some TD when CLE/BLE was turned off, and isn't quiesced * yet. finish_unlinks() restarts as needed, some upcoming INTR_SF. + * + * control and bulk EDs are doubly linked (ed_next, ed_prev), but + * periodic ones are singly linked (ed_next). that's because the + * periodic schedule encodes a tree like figure 3-5 in the ohci + * spec: each qh can have several "previous" nodes, and the tree + * doesn't have unused/idle descriptors. */ - switch (ed->type) { case PIPE_CONTROL: if (ohci->ed_controltail == NULL) { writel (ed->dma, &ohci->regs->ed_controlhead); } else { + ohci->ed_controltail->ed_next = ed; ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma); } ed->ed_prev = ohci->ed_controltail; @@ -187,6 +239,7 @@ static void ed_schedule (struct ohci_hcd *ohci, struct ed *ed) if (ohci->ed_bulktail == NULL) { writel (ed->dma, &ohci->regs->ed_bulkhead); } else { + ohci->ed_bulktail->ed_next = ed; ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma); } ed->ed_prev = ohci->ed_bulktail; @@ -198,74 +251,55 @@ static void ed_schedule (struct ohci_hcd *ohci, struct ed *ed) ohci->ed_bulktail = ed; break; - case PIPE_INTERRUPT: - load = ed->intriso.intr_info.int_load; - interval = ed->interval; - int_branch = ep_int_balance (ohci, interval, load); - ed->intriso.intr_info.int_branch = int_branch; - - for (i = 0; i < ep_rev (6, interval); i += inter) { - inter = 1; - for (ed_p = & (ohci->hcca->int_table [ep_rev (5, i) + int_branch]); - (*ed_p != 0) && ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->interval >= interval); - ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) - inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->interval); - ed->hwNextED = *ed_p; - *ed_p = cpu_to_le32 (ed->dma); + // case PIPE_INTERRUPT: + // case PIPE_ISOCHRONOUS: + default: + branch = balance (ohci, ed->interval, ed->load); + if (branch < 0) { + dbg ("%s: ERR %d, interval %d msecs, load %d", + ohci->hcd.self.bus_name, + branch, ed->interval, ed->load); + // FIXME if there are TDs queued, fail them! + return branch; } - wmb (); -#ifdef OHCI_VERBOSE_DEBUG - ohci_dump_periodic (ohci, "LINK_INT"); -#endif - break; - - case PIPE_ISOCHRONOUS: - ed->ed_prev = ohci->ed_isotail; - if (ohci->ed_isotail != NULL) { - ohci->ed_isotail->hwNextED = cpu_to_le32 (ed->dma); - } else { - for ( i = 0; i < NUM_INTS; i += inter) { - inter = 1; - for (ed_p = & (ohci->hcca->int_table [ep_rev (5, i)]); - *ed_p != 0; - ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) - inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->interval); - *ed_p = cpu_to_le32 (ed->dma); - } - } - wmb (); - ohci->ed_isotail = ed; -#ifdef OHCI_VERBOSE_DEBUG - ohci_dump_periodic (ohci, "LINK_ISO"); -#endif - break; + ed->branch = branch; + periodic_link (ohci, ed); } /* the HC may not see the schedule updates yet, but if it does * then they'll be properly ordered. */ + return 0; } /*-------------------------------------------------------------------------*/ /* scan the periodic table to find and unlink this ED */ -static void periodic_unlink ( - struct ohci_hcd *ohci, - struct ed *ed, - unsigned index, - unsigned period -) { - for (; index < NUM_INTS; index += period) { - __u32 *ed_p = &ohci->hcca->int_table [index]; +static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) +{ + int i; - while (*ed_p != 0) { - if ((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) { - *ed_p = ed->hwNextED; - break; - } - ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED); + for (i = ed->branch; i < NUM_INTS; i += ed->interval) { + struct ed *temp; + struct ed **prev = &ohci->periodic [i]; + u32 *prev_p = &ohci->hcca->int_table [i]; + + while (*prev && (temp = *prev) != ed) { + prev_p = &temp->hwNextED; + prev = &temp->ed_next; + } + if (*prev) { + *prev_p = ed->hwNextED; + *prev = ed->ed_next; } + ohci->load [i] -= ed->load; } + ohci->hcd.self.bandwidth_allocated -= ed->load / ed->interval; + + dbg ("%s: unlink %sed %p branch %d [%dus.], interval %d", + ohci->hcd.self.bus_name, + (ed->hwINFO & ED_ISO) ? "iso " : "", + ed, ed->branch, ed->load, ed->interval); } /* unlink an ed from one of the HC chains. @@ -275,8 +309,6 @@ static void periodic_unlink ( */ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) { - int i; - ed->hwINFO |= ED_SKIP; switch (ed->type) { @@ -289,13 +321,15 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_controlhead); } else { + ed->ed_prev->ed_next = ed->ed_next; ed->ed_prev->hwNextED = ed->hwNextED; } if (ohci->ed_controltail == ed) { ohci->ed_controltail = ed->ed_prev; + if (ohci->ed_controltail) + ohci->ed_controltail->ed_next = 0; } else { - (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED))) - ->ed_prev = ed->ed_prev; + ed->ed_next->ed_prev = ed->ed_prev; } break; @@ -308,50 +342,33 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_bulkhead); } else { + ed->ed_prev->ed_next = ed->ed_next; ed->ed_prev->hwNextED = ed->hwNextED; } if (ohci->ed_bulktail == ed) { ohci->ed_bulktail = ed->ed_prev; + if (ohci->ed_bulktail) + ohci->ed_bulktail->ed_next = 0; } else { - (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED))) - ->ed_prev = ed->ed_prev; + ed->ed_next->ed_prev = ed->ed_prev; } break; - case PIPE_INTERRUPT: - periodic_unlink (ohci, ed, ed->intriso.intr_info.int_branch, ed->interval); - for (i = ed->intriso.intr_info.int_branch; i < NUM_INTS; i += ed->interval) - ohci->ohci_int_load [i] -= ed->intriso.intr_info.int_load; -#ifdef OHCI_VERBOSE_DEBUG - ohci_dump_periodic (ohci, "UNLINK_INT"); -#endif - break; - - case PIPE_ISOCHRONOUS: - if (ohci->ed_isotail == ed) - ohci->ed_isotail = ed->ed_prev; - if (ed->hwNextED != 0) - (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED))) - ->ed_prev = ed->ed_prev; - - if (ed->ed_prev != NULL) - ed->ed_prev->hwNextED = ed->hwNextED; - else - periodic_unlink (ohci, ed, 0, 1); -#ifdef OHCI_VERBOSE_DEBUG - ohci_dump_periodic (ohci, "UNLINK_ISO"); -#endif + // case PIPE_INTERRUPT: + // case PIPE_ISOCHRONOUS: + default: + periodic_unlink (ohci, ed); break; } - /* FIXME Except for a couple of exceptionally clean unlink cases + /* NOTE: Except for a couple of exceptionally clean unlink cases * (like unlinking the only c/b ED, with no TDs) HCs may still be - * caching this (till SOF). - * - * To avoid racing with the hardware, this needs to use ED_UNLINK - * and delay til next INTR_SF. Merge with start_urb_unlink(). + * caching this operational ED (or its address). Safe unlinking + * involves not marking it ED_IDLE till INTR_SF; we always do that + * if td_list isn't empty. Otherwise the race is small; but ... */ - ed->state = ED_IDLE; + if (ed->state == ED_OPER) + ed->state = ED_IDLE; } @@ -369,7 +386,6 @@ static struct ed *ed_get ( ) { int is_out = !usb_pipein (pipe); int type = usb_pipetype (pipe); - int bus_msecs = 0; struct hcd_dev *dev = (struct hcd_dev *) udev->hcpriv; struct ed *ed; unsigned ep; @@ -378,9 +394,6 @@ static struct ed *ed_get ( ep = usb_pipeendpoint (pipe) << 1; if (type != PIPE_CONTROL && is_out) ep |= 1; - if (type == PIPE_INTERRUPT) - bus_msecs = usb_calc_bus_time (udev->speed, !is_out, 0, - usb_maxpacket (udev, pipe, is_out)) / 1000; spin_lock_irqsave (&ohci->lock, flags); @@ -422,23 +435,25 @@ static struct ed *ed_get ( info = cpu_to_le32 (info); if (udev->speed == USB_SPEED_LOW) info |= ED_LOWSPEED; - /* control transfers store pids in tds */ + /* only control transfers store pids in tds */ if (type != PIPE_CONTROL) { info |= is_out ? ED_OUT : ED_IN; - if (type == PIPE_ISOCHRONOUS) - info |= ED_ISO; - if (type == PIPE_INTERRUPT) { - ed->intriso.intr_info.int_load = bus_msecs; - if (interval > 32) + if (type != PIPE_BULK) { + /* periodic transfers... */ + if (type == PIPE_ISOCHRONOUS) + info |= ED_ISO; + else if (interval > 32) /* iso can be bigger */ interval = 32; + ed->interval = interval; + ed->load = usb_calc_bus_time ( + udev->speed, !is_out, + type == PIPE_ISOCHRONOUS, + usb_maxpacket (udev, pipe, is_out)) + / 1000; } } ed->hwINFO = info; - /* value ignored except on periodic EDs, where - * we know it's already a power of 2 - */ - ed->interval = interval; #ifdef DEBUG /* * There are two other cases we ought to change hwINFO, both during @@ -473,8 +488,9 @@ done: */ static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed) { - ed_deschedule (ohci, ed); + ed->hwINFO |= ED_DEQUEUE; ed->state = ED_UNLINK; + ed_deschedule (ohci, ed); /* SF interrupt might get delayed; record the frame counter value that * indicates when the HC isn't looking at it, so concurrent unlinks @@ -483,7 +499,9 @@ static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed) */ ed->tick = le16_to_cpu (ohci->hcca->frame_no) + 1; + /* rm_list is just singly linked, for simplicity */ ed->ed_next = ohci->ed_rm_list; + ed->ed_prev = 0; ohci->ed_rm_list = ed; /* enable SOF interrupt */ @@ -529,7 +547,6 @@ td_fill (unsigned int info, /* use this td as the next dummy */ td_pt = urb_priv->td [index]; - td_pt->hwNextTD = 0; /* fill the old dummy TD */ td = urb_priv->td [index] = urb_priv->ed->dummy; @@ -547,7 +564,7 @@ td_fill (unsigned int info, if (is_iso) { td->hwCBP = cpu_to_le32 (data & 0xFFFFF000); td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000); - td->ed->intriso.last_iso = info & 0xffff; + td->ed->last_iso = info & 0xffff; } else { td->hwCBP = cpu_to_le32 (data); } @@ -608,9 +625,11 @@ static void td_submit_urb ( /* Bulk and interrupt are identical except for where in the schedule * their EDs live. */ - // case PIPE_BULK: - // case PIPE_INTERRUPT: - default: + case PIPE_INTERRUPT: + /* ... and periodic urbs have extra accounting */ + ohci->hcd.self.bandwidth_int_reqs++; + /* FALLTHROUGH */ + case PIPE_BULK: info = is_out ? TD_T_TOGGLE | TD_CC | TD_DP_OUT : TD_T_TOGGLE | TD_CC | TD_DP_IN; @@ -676,6 +695,7 @@ static void td_submit_urb ( data + urb->iso_frame_desc [cnt].offset, urb->iso_frame_desc [cnt].length, urb, cnt); } + ohci->hcd.self.bandwidth_isoc_reqs++; break; } if (urb_priv->length != cnt) @@ -707,8 +727,12 @@ static void td_done (struct urb *urb, struct td *td) if (usb_pipeout (urb->pipe)) dlen = urb->iso_frame_desc [td->index].length; - else + else { + /* short reads are always OK for ISO */ + if (cc == TD_DATAUNDERRUN) + cc = TD_CC_NOERROR; dlen = tdPSW & 0x3ff; + } urb->actual_length += dlen; urb->iso_frame_desc [td->index].actual_length = dlen; urb->iso_frame_desc [td->index].status = cc_to_error [cc]; @@ -802,6 +826,7 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) if (td_list->ed->hwHeadP & ED_H) { if (urb_priv && ((td_list->index + 1) < urb_priv->length)) { +#ifdef DEBUG struct urb *urb = td_list->urb; /* help for troubleshooting: */ @@ -817,6 +842,7 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) 1 + td_list->index, urb_priv->length, cc, cc_to_error [cc]); +#endif td_list->ed->hwHeadP = (urb_priv->td [urb_priv->length - 1]->hwNextTD & __constant_cpu_to_le32 (TD_MASK)) @@ -872,8 +898,7 @@ rescan_all: * we call a completion since it might have unlinked * another (earlier) urb * - * FIXME use td_list to scan, not ed hashtables. - * completely abolish ed hashtables! + * FIXME use td_list to scan, not td hashtables. */ rescan_this: completed = 0; @@ -894,8 +919,7 @@ rescan_this: td_done (urb, td); urb_priv->td_cnt++; - *td_p = td->hwNextTD | (*td_p - & __constant_cpu_to_le32 (0x3)); + *td_p = td->hwNextTD | (*td_p & ~TD_MASK); /* URB is done; clean up */ if (urb_priv->td_cnt == urb_priv->length) { diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 4af5cdf0aa34..d2cfdc659e24 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -5,7 +5,6 @@ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> * * This file is licenced under the GPL. - * $Id: ohci.h,v 1.6 2002/03/22 16:04:54 dbrownell Exp $ */ /* @@ -18,13 +17,16 @@ struct ed { /* first fields are hardware-specified, le32 */ __u32 hwINFO; /* endpoint config bitmap */ + /* info bits defined by hcd */ +#define ED_DEQUEUE __constant_cpu_to_le32(1 << 27) + /* info bits defined by the hardware */ #define ED_ISO __constant_cpu_to_le32(1 << 15) #define ED_SKIP __constant_cpu_to_le32(1 << 14) #define ED_LOWSPEED __constant_cpu_to_le32(1 << 13) #define ED_OUT __constant_cpu_to_le32(0x01 << 11) #define ED_IN __constant_cpu_to_le32(0x02 << 11) __u32 hwTailP; /* tail of TD list */ - __u32 hwHeadP; /* head of TD list */ + __u32 hwHeadP; /* head of TD list (hc r/w) */ #define ED_C __constant_cpu_to_le32(0x02) /* toggle carry */ #define ED_H __constant_cpu_to_le32(0x01) /* halted */ __u32 hwNextED; /* next ED in list */ @@ -48,14 +50,12 @@ struct ed { #define ED_OPER 0x02 /* IS linked to hc */ u8 type; /* PIPE_{BULK,...} */ - u16 interval; /* interrupt, isochronous */ - union { - struct intr_info { /* interrupt */ - u8 int_branch; - u8 int_load; - } intr_info; - u16 last_iso; /* isochronous */ - } intriso; + + /* periodic scheduling params (for intr and iso) */ + u8 branch; + u16 interval; + u16 load; + u16 last_iso; /* iso only */ /* HC may see EDs on rm_list until next frame (frame_no == tick) */ u16 tick; @@ -335,10 +335,8 @@ struct hash_list_t { }; #define TD_HASH_SIZE 64 /* power'o'two */ -#define ED_HASH_SIZE 64 /* power'o'two */ #define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 5)) % TD_HASH_SIZE) -#define ED_HASH_FUNC(ed_dma) ((ed_dma ^ (ed_dma >> 5)) % ED_HASH_SIZE) /* @@ -373,7 +371,7 @@ struct ohci_hcd { struct ed *ed_bulktail; /* last in bulk list */ struct ed *ed_controltail; /* last in ctrl list */ - struct ed *ed_isotail; /* last in iso list */ + struct ed *periodic [NUM_INTS]; /* shadow int_table */ /* * memory management for queue data structures @@ -381,14 +379,13 @@ struct ohci_hcd { struct pci_pool *td_cache; struct pci_pool *ed_cache; struct hash_list_t td_hash [TD_HASH_SIZE]; - struct hash_list_t ed_hash [ED_HASH_SIZE]; /* * driver state */ int disabled; /* e.g. got a UE, we're hung */ int sleeping; - int ohci_int_load [NUM_INTS]; + int load [NUM_INTS]; u32 hc_control; /* copy of hc control reg */ unsigned long flags; /* for HC bugs */ diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 150ae60fe1e6..161420c58fb9 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -105,12 +105,10 @@ static void wakeup_hc(struct uhci_hcd *uhci); /* to make sure it doesn't hog all of the bandwidth */ #define DEPTH_INTERVAL 5 -#define MAX_URB_LOOP 2048 /* Maximum number of linked URB's */ - /* * Technically, updating td->status here is a race, but it's not really a * problem. The worst that can happen is that we set the IOC bit again - * generating a spurios interrupt. We could fix this by creating another + * generating a spurious interrupt. We could fix this by creating another * QH and leaving the IOC bit always set, but then we would have to play * games with the FSBR code to make sure we get the correct order in all * the cases. I don't think it's worth the effort @@ -148,7 +146,7 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *d dma_addr_t dma_handle; struct uhci_td *td; - td = pci_pool_alloc(uhci->td_pool, GFP_DMA | GFP_ATOMIC, &dma_handle); + td = pci_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle); if (!td) return NULL; @@ -273,7 +271,7 @@ out: /* * Inserts a td into qh list at the top. */ -static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, int breadth) +static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, u32 breadth) { struct list_head *tmp, *head; struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; @@ -290,7 +288,7 @@ static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, int bread td = list_entry(tmp, struct uhci_td, list); /* Add the first TD to the QH element pointer */ - qh->element = cpu_to_le32(td->dma_handle) | (breadth ? 0 : UHCI_PTR_DEPTH); + qh->element = cpu_to_le32(td->dma_handle) | breadth; ptd = td; @@ -301,7 +299,7 @@ static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, int bread tmp = tmp->next; - ptd->link = cpu_to_le32(td->dma_handle) | (breadth ? 0 : UHCI_PTR_DEPTH); + ptd->link = cpu_to_le32(td->dma_handle) | breadth; ptd = td; } @@ -311,10 +309,6 @@ static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, int bread static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td) { -/* - if (!list_empty(&td->list) || !list_empty(&td->fl_list)) - dbg("td %p is still in URB list!", td); -*/ if (!list_empty(&td->list)) dbg("td %p is still in list!", td); if (!list_empty(&td->fl_list)) @@ -331,7 +325,7 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *d dma_addr_t dma_handle; struct uhci_qh *qh; - qh = pci_pool_alloc(uhci->qh_pool, GFP_DMA | GFP_ATOMIC, &dma_handle); + qh = pci_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); if (!qh) return NULL; @@ -365,43 +359,57 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) } /* + * Append this urb's qh after the last qh in skelqh->list * MUST be called with uhci->frame_list_lock acquired + * + * Note that urb_priv.queue_list doesn't have a separate queue head; + * it's a ring with every element "live". */ static void _uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct urb *urb) { struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct list_head *head, *tmp; + struct list_head *tmp; struct uhci_qh *lqh; /* Grab the last QH */ lqh = list_entry(skelqh->list.prev, struct uhci_qh, list); + /* Patch this endpoint's URBs' QHs to point to the next skelQH: + * SkelQH --> ... lqh --> NewQH --> NextSkelQH + * Do this first, so the HC always sees the right QH after this one. + */ + list_for_each (tmp, &urbp->queue_list) { + struct urb_priv *turbp = + list_entry(tmp, struct urb_priv, queue_list); + + turbp->qh->link = lqh->link; + } + urbp->qh->link = lqh->link; + wmb(); /* Ordering is important */ + + /* Patch QHs for previous endpoint's queued URBs? HC goes + * here next, not to the NextSkelQH it now points to. + * + * lqh --> td ... --> qh ... --> td --> qh ... --> td + * | | | + * v v v + * +<----------------+-----------------+ + * v + * NewQH --> td ... --> td + * | + * v + * ... + * + * The HC could see (and use!) any of these as we write them. + */ if (lqh->urbp) { - head = &lqh->urbp->queue_list; - tmp = head->next; - while (head != tmp) { + list_for_each (tmp, &lqh->urbp->queue_list) { struct urb_priv *turbp = list_entry(tmp, struct urb_priv, queue_list); - tmp = tmp->next; - turbp->qh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; } } - - head = &urbp->queue_list; - tmp = head->next; - while (head != tmp) { - struct urb_priv *turbp = - list_entry(tmp, struct urb_priv, queue_list); - - tmp = tmp->next; - - turbp->qh->link = lqh->link; - } - - urbp->qh->link = lqh->link; - mb(); /* Ordering is important */ lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; list_add_tail(&urbp->qh->list, &skelqh->list); @@ -416,6 +424,9 @@ static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct spin_unlock_irqrestore(&uhci->frame_list_lock, flags); } +/* start removal of qh from schedule; it finishes next frame. + * TDs should be unlinked before this is called. + */ static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) { unsigned long flags; @@ -869,12 +880,12 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb) urbp->qh = qh; qh->urbp = urbp; - /* Low speed or small transfers gets a different queue and treatment */ + /* Low speed transfers get a different queue, and won't hog the bus */ if (urb->dev->speed == USB_SPEED_LOW) { - uhci_insert_tds_in_qh(qh, urb, 0); + uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_DEPTH); uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb); } else { - uhci_insert_tds_in_qh(qh, urb, 1); + uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH); uhci_insert_qh(uhci, uhci->skel_hs_control_qh, urb); uhci_inc_fsbr(uhci, urb); } @@ -914,9 +925,9 @@ static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb) urbp->qh->urbp = urbp; /* One TD, who cares about Breadth first? */ - uhci_insert_tds_in_qh(urbp->qh, urb, 0); + uhci_insert_tds_in_qh(urbp->qh, urb, UHCI_PTR_DEPTH); - /* Low speed or small transfers gets a different queue and treatment */ + /* Low speed transfers get a different queue */ if (urb->dev->speed == USB_SPEED_LOW) uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb); else @@ -1242,8 +1253,8 @@ static int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct urb * urbp->qh = qh; qh->urbp = urbp; - /* Always assume breadth first */ - uhci_insert_tds_in_qh(qh, urb, 1); + /* Always breadth first */ + uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH); if (eurb) uhci_append_queued_urb(uhci, eurb, urb); @@ -1487,6 +1498,10 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags) spin_unlock_irqrestore(&uhci->urb_list_lock, flags); + if (ret != -EINPROGRESS) { + uhci_destroy_urb_priv (uhci, urb); + return ret; + } return 0; } @@ -1795,8 +1810,7 @@ static void uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb) spin_lock_irqsave(&urb->lock, flags); - killed = (urb->status == -ENOENT || urb->status == -ECONNABORTED || - urb->status == -ECONNRESET); + killed = (urb->status == -ENOENT || urb->status == -ECONNRESET); resubmit_interrupt = (usb_pipetype(urb->pipe) == PIPE_INTERRUPT && urb->interval); @@ -1817,9 +1831,7 @@ static void uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb) if (resubmit_interrupt) /* Recheck the status. The completion handler may have */ /* unlinked the resubmitting interrupt URB */ - killed = (urb->status == -ENOENT || - urb->status == -ECONNABORTED || - urb->status == -ECONNRESET); + killed = (urb->status == -ENOENT || urb->status == -ECONNRESET); if (resubmit_interrupt && !killed) { urb->dev = dev; @@ -2016,19 +2028,12 @@ static void start_hc(struct uhci_hcd *uhci) uhci->hcd.state = USB_STATE_READY; } -#ifdef CONFIG_PROC_FS -static int uhci_num = 0; -#endif - /* * De-allocate all resources.. */ static void release_uhci(struct uhci_hcd *uhci) { int i; -#ifdef CONFIG_PROC_FS - char buf[8]; -#endif for (i = 0; i < UHCI_NUM_SKELQH; i++) if (uhci->skelqh[i]) { @@ -2053,15 +2058,13 @@ static void release_uhci(struct uhci_hcd *uhci) } if (uhci->fl) { - pci_free_consistent(uhci->dev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle); + pci_free_consistent(uhci->hcd.pdev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle); uhci->fl = NULL; } #ifdef CONFIG_PROC_FS if (uhci->proc_entry) { - sprintf(buf, "hc%d", uhci->num); - - remove_proc_entry(buf, uhci_proc_root); + remove_proc_entry(uhci->hcd.self.bus_name, uhci_proc_root); uhci->proc_entry = NULL; } #endif @@ -2086,33 +2089,20 @@ static void release_uhci(struct uhci_hcd *uhci) static int __devinit uhci_start(struct usb_hcd *hcd) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); - struct pci_dev *dev = hcd->pdev; int retval = -EBUSY; int i, port; + unsigned io_size; dma_addr_t dma_handle; + struct usb_device *udev; #ifdef CONFIG_PROC_FS - char buf[8]; struct proc_dir_entry *ent; #endif - uhci->dev = dev; - - /* Should probably move to core/hcd.c */ - if (pci_set_dma_mask(dev, 0xFFFFFFFF)) { - err("couldn't set PCI dma mask"); - retval = -ENODEV; - goto err_pci_set_dma_mask; - } - - uhci->io_addr = pci_resource_start(dev, hcd->region); - uhci->io_size = pci_resource_len(dev, hcd->region); + uhci->io_addr = (unsigned) hcd->regs; + io_size = pci_resource_len(hcd->pdev, hcd->region); #ifdef CONFIG_PROC_FS - uhci->num = uhci_num++; - - sprintf(buf, "hc%d", uhci->num); - - ent = create_proc_entry(buf, S_IFREG|S_IRUGO|S_IWUSR, uhci_proc_root); + ent = create_proc_entry(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR, uhci_proc_root); if (!ent) { err("couldn't create uhci proc entry"); retval = -ENOMEM; @@ -2148,7 +2138,7 @@ static int __devinit uhci_start(struct usb_hcd *hcd) spin_lock_init(&uhci->frame_list_lock); - uhci->fl = pci_alloc_consistent(dev, sizeof(*uhci->fl), &dma_handle); + uhci->fl = pci_alloc_consistent(hcd->pdev, sizeof(*uhci->fl), &dma_handle); if (!uhci->fl) { err("unable to allocate consistent memory for frame list"); goto err_alloc_fl; @@ -2158,15 +2148,15 @@ static int __devinit uhci_start(struct usb_hcd *hcd) uhci->fl->dma_handle = dma_handle; - uhci->td_pool = pci_pool_create("uhci_td", dev, - sizeof(struct uhci_td), 16, 0, GFP_DMA | GFP_ATOMIC); + uhci->td_pool = pci_pool_create("uhci_td", hcd->pdev, + sizeof(struct uhci_td), 16, 0, GFP_ATOMIC); if (!uhci->td_pool) { err("unable to create td pci_pool"); goto err_create_td_pool; } - uhci->qh_pool = pci_pool_create("uhci_qh", dev, - sizeof(struct uhci_qh), 16, 0, GFP_DMA | GFP_ATOMIC); + uhci->qh_pool = pci_pool_create("uhci_qh", hcd->pdev, + sizeof(struct uhci_qh), 16, 0, GFP_ATOMIC); if (!uhci->qh_pool) { err("unable to create qh pci_pool"); goto err_create_qh_pool; @@ -2178,7 +2168,7 @@ static int __devinit uhci_start(struct usb_hcd *hcd) /* they may have more but give no way to determine how many they */ /* have. However, according to the UHCI spec, Bit 7 is always set */ /* to 1. So we try to use this to our advantage */ - for (port = 0; port < (uhci->io_size - 0x10) / 2; port++) { + for (port = 0; port < (io_size - 0x10) / 2; port++) { unsigned int portstatus; portstatus = inw(uhci->io_addr + 0x10 + (port * 2)); @@ -2197,13 +2187,13 @@ static int __devinit uhci_start(struct usb_hcd *hcd) uhci->rh_numports = port; - hcd->self.root_hub = uhci->rh_dev = usb_alloc_dev(NULL, &hcd->self); - if (!uhci->rh_dev) { + hcd->self.root_hub = udev = usb_alloc_dev(NULL, &hcd->self); + if (!udev) { err("unable to allocate root hub"); goto err_alloc_root_hub; } - uhci->skeltd[0] = uhci_alloc_td(uhci, uhci->rh_dev); + uhci->skeltd[0] = uhci_alloc_td(uhci, udev); if (!uhci->skeltd[0]) { err("unable to allocate TD 0"); goto err_alloc_skeltd; @@ -2216,7 +2206,7 @@ static int __devinit uhci_start(struct usb_hcd *hcd) for (i = 1; i < 9; i++) { struct uhci_td *td; - td = uhci->skeltd[i] = uhci_alloc_td(uhci, uhci->rh_dev); + td = uhci->skeltd[i] = uhci_alloc_td(uhci, udev); if (!td) { err("unable to allocate TD %d", i); goto err_alloc_skeltd; @@ -2227,14 +2217,14 @@ static int __devinit uhci_start(struct usb_hcd *hcd) td->link = cpu_to_le32(uhci->skeltd[i - 1]->dma_handle); } - uhci->skel_term_td = uhci_alloc_td(uhci, uhci->rh_dev); + uhci->skel_term_td = uhci_alloc_td(uhci, udev); if (!uhci->skel_term_td) { err("unable to allocate skel TD term"); goto err_alloc_skeltd; } for (i = 0; i < UHCI_NUM_SKELQH; i++) { - uhci->skelqh[i] = uhci_alloc_qh(uhci, uhci->rh_dev); + uhci->skelqh[i] = uhci_alloc_qh(uhci, udev); if (!uhci->skelqh[i]) { err("unable to allocate QH %d", i); goto err_alloc_skelqh; @@ -2303,12 +2293,12 @@ static int __devinit uhci_start(struct usb_hcd *hcd) init_stall_timer(hcd); /* disable legacy emulation */ - pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT); + pci_write_config_word(hcd->pdev, USBLEGSUP, USBLEGSUP_DEFAULT); - usb_connect(uhci->rh_dev); - uhci->rh_dev->speed = USB_SPEED_FULL; + usb_connect(udev); + udev->speed = USB_SPEED_FULL; - if (usb_register_root_hub(uhci->rh_dev, &dev->dev) != 0) { + if (usb_register_root_hub(udev, &hcd->pdev->dev) != 0) { err("unable to start root hub"); retval = -ENOMEM; goto err_start_root_hub; @@ -2322,7 +2312,7 @@ static int __devinit uhci_start(struct usb_hcd *hcd) err_start_root_hub: reset_hc(uhci); - del_timer(&uhci->stall_timer); + del_timer_sync(&uhci->stall_timer); for (i = 0; i < UHCI_NUM_SKELQH; i++) if (uhci->skelqh[i]) { @@ -2338,8 +2328,8 @@ err_alloc_skelqh: } err_alloc_skeltd: - usb_free_dev(uhci->rh_dev); - uhci->rh_dev = NULL; + usb_free_dev(udev); + hcd->self.root_hub = NULL; err_alloc_root_hub: pci_pool_destroy(uhci->qh_pool); @@ -2350,19 +2340,17 @@ err_create_qh_pool: uhci->td_pool = NULL; err_create_td_pool: - pci_free_consistent(dev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle); + pci_free_consistent(hcd->pdev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle); uhci->fl = NULL; err_alloc_fl: #ifdef CONFIG_PROC_FS - remove_proc_entry(buf, uhci_proc_root); + remove_proc_entry(hcd->self.bus_name, uhci_proc_root); uhci->proc_entry = NULL; err_create_proc_entry: #endif -err_pci_set_dma_mask: - return retval; } @@ -2370,10 +2358,7 @@ static void uhci_stop(struct usb_hcd *hcd) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); - if (uhci->rh_dev) - usb_disconnect(&uhci->rh_dev); - - del_timer(&uhci->stall_timer); + del_timer_sync(&uhci->stall_timer); /* * At this point, we're guaranteed that no new connects can be made @@ -2402,7 +2387,7 @@ static int uhci_resume(struct usb_hcd *hcd) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); - pci_set_master(uhci->dev); + pci_set_master(uhci->hcd.pdev); reset_hc(uhci); start_hc(uhci); diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 2de75a2b577f..809434e6e78b 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -65,6 +65,7 @@ #define UHCI_PTR_TERM cpu_to_le32(0x0001) #define UHCI_PTR_QH cpu_to_le32(0x0002) #define UHCI_PTR_DEPTH cpu_to_le32(0x0004) +#define UHCI_PTR_BREADTH cpu_to_le32(0x0000) #define UHCI_NUMFRAMES 1024 /* in the frame list [array] */ #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ @@ -80,6 +81,19 @@ struct uhci_frame_list { struct urb_priv; +/* One role of a QH is to hold a queue of TDs for some endpoint. Each QH is + * used with one URB, and qh->element (updated by the HC) is either: + * - the next unprocessed TD for the URB, or + * - UHCI_PTR_TERM (when there's no more traffic for this endpoint), or + * - the QH for the next URB queued to the same endpoint. + * + * The other role of a QH is to serve as a "skeleton" framelist entry, so we + * can easily splice a QH for some endpoint into the schedule at the right + * place. Then qh->element is UHCI_PTR_TERM. + * + * In the frame list, qh->link maintains a list of QHs seen by the HC: + * skel1 --> ep1-qh --> ep2-qh --> ... --> skel2 --> ... + */ struct uhci_qh { /* Hardware fields */ __u32 link; /* Next queue */ @@ -156,6 +170,9 @@ struct uhci_qh { * * Alas, not anymore, we have more than 4 words for software, woops. * Everything still works tho, surprise! -jerdfelt + * + * td->link points to either another TD (not necessarily for the same urb or + * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs) */ struct uhci_td { /* Hardware fields */ @@ -172,7 +189,7 @@ struct uhci_td { struct list_head list; /* P: urb->lock */ - int frame; + int frame; /* for iso: what frame? */ struct list_head fl_list; /* P: uhci->frame_list_lock */ } __attribute__((aligned(16))); @@ -217,6 +234,22 @@ struct uhci_td { * * To keep with Linus' nomenclature, this is called the QH skeleton. These * labels (below) are only signficant to the root hub's QH's + * + * + * NOTE: That ASCII art doesn't match the current (August 2002) code, in + * more ways than just not using QHs for ISO. + * + * NOTE: Another way to look at the UHCI schedules is to compare them to what + * other host controller interfaces use. EHCI, OHCI, and UHCI all have tables + * of transfers that the controller scans, frame by frame, and which hold the + * scheduled periodic transfers. The key differences are that UHCI + * + * (a) puts control and bulk transfers into that same table; the others + * have separate data structures for non-periodic transfers. + * (b) lets QHs be linked from TDs, not just other QHs, since they don't + * hold endpoint data. this driver chooses to use one QH per URB. + * (c) needs more TDs, since it uses one per packet. the data toggle + * is stored in those TDs, along with all other endpoint state. */ #define UHCI_NUM_SKELTD 10 @@ -275,7 +308,7 @@ static inline int __interval_to_skel(int interval) return 7; /* int128 for 128-255 ms (Max.) */ } -#define hcd_to_uhci(hcd_ptr) list_entry(hcd_ptr, struct uhci_hcd, hcd) +#define hcd_to_uhci(hcd_ptr) container_of(hcd_ptr, struct uhci_hcd, hcd) /* * This describes the full uhci information. @@ -286,18 +319,13 @@ static inline int __interval_to_skel(int interval) struct uhci_hcd { struct usb_hcd hcd; - struct pci_dev *dev; - #ifdef CONFIG_PROC_FS /* procfs */ - int num; struct proc_dir_entry *proc_entry; #endif /* Grabbed from PCI */ - int irq; unsigned int io_addr; - unsigned int io_size; struct pci_pool *qh_pool; struct pci_pool *td_pool; @@ -329,7 +357,6 @@ struct uhci_hcd { spinlock_t complete_list_lock; struct list_head complete_list; /* P: uhci->complete_list_lock */ - struct usb_device *rh_dev; /* Root hub */ int rh_numports; struct timer_list stall_timer; diff --git a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c index 9c9550e5cce7..f1248f7a3f07 100644 --- a/drivers/usb/image/scanner.c +++ b/drivers/usb/image/scanner.c @@ -774,7 +774,7 @@ ioctl_scanner(struct inode *inode, struct file *file, if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg))) return -EFAULT; - nb = le16_to_cpup(&cmsg.req.wLength); + nb = cmsg.req.wLength; if (nb > sizeof(buf)) return -EINVAL; @@ -789,8 +789,8 @@ ioctl_scanner(struct inode *inode, struct file *file, ret = usb_control_msg(dev, pipe, cmsg.req.bRequest, cmsg.req.bRequestType, - le16_to_cpup(&cmsg.req.wValue), - le16_to_cpup(&cmsg.req.wIndex), + cmsg.req.wValue, + cmsg.req.wIndex, buf, nb, HZ); if (ret < 0) { diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c index 0df4777f0bd4..7fb881cbadc3 100644 --- a/drivers/usb/media/se401.c +++ b/drivers/usb/media/se401.c @@ -25,7 +25,7 @@ * - Jeroen Vreeken */ -static const char version[] = "0.23"; +static const char version[] = "0.24"; #include <linux/config.h> #include <linux/module.h> @@ -980,6 +980,34 @@ static int se401_newframe(struct usb_se401 *se401, int framenr) return 0; } +static void usb_se401_remove_disconnected (struct usb_se401 *se401) +{ + int i; + + se401->dev = NULL; + + for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) { + usb_unlink_urb(se401->urb[i]); + usb_free_urb(se401->urb[i]); + se401->urb[i] = NULL; + kfree(se401->sbuf[i].data); + } + for (i=0; i<SE401_NUMSCRATCH; i++) if (se401->scratch[i].data) { + kfree(se401->scratch[i].data); + } + if (se401->inturb) { + usb_unlink_urb(se401->inturb); + usb_free_urb(se401->inturb); + } + info("%s disconnected", se401->camera_name); + + /* Free the memory */ + kfree(se401->width); + kfree(se401->height); + kfree(se401); +} + + /**************************************************************************** * @@ -1015,20 +1043,16 @@ static int se401_close(struct inode *inode, struct file *file) struct usb_se401 *se401 = (struct usb_se401 *)dev; int i; - for (i=0; i<SE401_NUMFRAMES; i++) - se401->frame[i].grabstate=FRAME_UNUSED; - if (se401->streaming) - se401_stop_stream(se401); - rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES); - se401->user=0; - if (se401->removed) { - kfree(se401->width); - kfree(se401->height); - kfree(se401); - se401 = NULL; + usb_se401_remove_disconnected(se401); info("device unregistered"); + } else { + for (i=0; i<SE401_NUMFRAMES; i++) + se401->frame[i].grabstate=FRAME_UNUSED; + if (se401->streaming) + se401_stop_stream(se401); + se401->user=0; } file->private_data = NULL; return 0; @@ -1302,7 +1326,7 @@ static struct video_device se401_template = { /***************************/ -static int se401_init(struct usb_se401 *se401) +static int se401_init(struct usb_se401 *se401, int button) { int i=0, rc; unsigned char cp[0x40]; @@ -1367,22 +1391,25 @@ static int se401_init(struct usb_se401 *se401) se401->readcount=0; /* Start interrupt transfers for snapshot button */ - se401->inturb=usb_alloc_urb(0, GFP_KERNEL); - if (!se401->inturb) { - info("Allocation of inturb failed"); - return 1; - } - FILL_INT_URB(se401->inturb, se401->dev, - usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT), - &se401->button, sizeof(se401->button), - se401_button_irq, - se401, - HZ/10 - ); - if (usb_submit_urb(se401->inturb, GFP_KERNEL)) { - info("int urb burned down"); - return 1; - } + if (button) { + se401->inturb=usb_alloc_urb(0, GFP_KERNEL); + if (!se401->inturb) { + info("Allocation of inturb failed"); + return 1; + } + FILL_INT_URB(se401->inturb, se401->dev, + usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT), + &se401->button, sizeof(se401->button), + se401_button_irq, + se401, + HZ/10 + ); + if (usb_submit_urb(se401->inturb, GFP_KERNEL)) { + info("int urb burned down"); + return 1; + } + } else + se401->inturb=NULL; /* Flash the led */ se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0); @@ -1399,6 +1426,7 @@ static void* se401_probe(struct usb_device *dev, unsigned int ifnum, struct usb_interface_descriptor *interface; struct usb_se401 *se401; char *camera_name=NULL; + int button=1; /* We don't handle multi-config cameras */ if (dev->descriptor.bNumConfigurations != 1) @@ -1422,6 +1450,7 @@ static void* se401_probe(struct usb_device *dev, unsigned int ifnum, } else if (dev->descriptor.idVendor == 0x047d && dev->descriptor.idProduct == 0x5003) { camera_name="Kensington VideoCAM 67016"; + button=0; } else return NULL; @@ -1447,7 +1476,7 @@ static void* se401_probe(struct usb_device *dev, unsigned int ifnum, info("firmware version: %02x", dev->descriptor.bcdDevice & 255); - if (se401_init(se401)) { + if (se401_init(se401, button)) { kfree(se401); return NULL; } @@ -1479,45 +1508,18 @@ static void se401_disconnect(struct usb_device *dev, void *ptr) if (!se401->user){ usb_se401_remove_disconnected(se401); } else { - se401->removed = 1; - } -} + se401->frame[0].grabstate = FRAME_ERROR; + se401->frame[0].grabstate = FRAME_ERROR; -static inline void usb_se401_remove_disconnected (struct usb_se401 *se401) -{ - int i; - - se401->dev = NULL; - se401->frame[0].grabstate = FRAME_ERROR; - se401->frame[1].grabstate = FRAME_ERROR; - - se401->streaming = 0; - - wake_up_interruptible(&se401->wq); - - for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) { - usb_unlink_urb(se401->urb[i]); - usb_free_urb(se401->urb[i]); - se401->urb[i] = NULL; - kfree(se401->sbuf[i].data); - } - for (i=0; i<SE401_NUMSCRATCH; i++) if (se401->scratch[i].data) { - kfree(se401->scratch[i].data); - } - if (se401->inturb) { - usb_unlink_urb(se401->inturb); - usb_free_urb(se401->inturb); + se401->streaming = 0; + + wake_up_interruptible(&se401->wq); + se401->removed = 1; } - info("%s disconnected", se401->camera_name); - #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) destroy_proc_se401_cam(se401); #endif - /* Free the memory */ - kfree(se401->width); - kfree(se401->height); - kfree(se401); } static struct usb_driver se401_driver = { diff --git a/drivers/usb/media/se401.h b/drivers/usb/media/se401.h index 861210147ca9..c8f97d089216 100644 --- a/drivers/usb/media/se401.h +++ b/drivers/usb/media/se401.h @@ -230,7 +230,6 @@ struct usb_se401 { int nullpackets; }; -static inline void usb_se401_remove_disconnected (struct usb_se401 *se401); #endif diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index 799c5df48f53..2562a704a438 100644 --- a/drivers/usb/net/kaweth.c +++ b/drivers/usb/net/kaweth.c @@ -567,6 +567,8 @@ static void kaweth_usb_receive(struct urb *urb) return; } + skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ + skb->dev = net; eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0); diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h index d231998a4698..b01f5cef133b 100644 --- a/drivers/usb/net/pegasus.h +++ b/drivers/usb/net/pegasus.h @@ -191,6 +191,8 @@ PEGASUS_DEV( "Billionton USBE-100", VENDOR_BILLIONTON, 0x8511, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Corega FEter USB-TX", VENDOR_COREGA, 0x0004, DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "Corega FEter", VENDOR_COREGA, 0x0004, + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4001, LINKSYS_GPIO_RESET ) PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4002, @@ -205,7 +207,7 @@ PEGASUS_DEV( "D-Link DSB-650TX(PNA)", VENDOR_DLINK, 0x4003, DEFAULT_GPIO_RESET | HAS_HOME_PNA ) PEGASUS_DEV( "D-Link DSB-650", VENDOR_DLINK, 0xabc1, DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "ELCON EPLC10Mi USB to Powerline Adapter", VENDOR_ELCON, 0x0002, +PEGASUS_DEV( "GOLDPFEIL USB Adapter", VENDOR_ELCON, 0x0002, DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA ) PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000, DEFAULT_GPIO_RESET ) @@ -254,7 +256,7 @@ PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100, PEGASUS_DEV( "SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001, - DEFAULT_GPIO_RESET ) + DEFAULT_GPIO_RESET | PEGASUS_II ) #endif /* PEGASUS_DEV */ diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index c5bc8e92c8cf..4904c614f40d 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -2086,7 +2086,12 @@ static const struct usb_device_id products [] = { // 1183 = 0x049F, both used as hex values? USB_DEVICE (0x049F, 0x505A), // Compaq "Itsy" .driver_info = (unsigned long) &linuxdev_info, +}, { + USB_DEVICE (0x0E7E, 0x1001), // G.Mate "Yopy" + .driver_info = (unsigned long) &linuxdev_info, }, + // NOTE: the Sharp Zaurus uses a modified version of + // this driver, which is not interoperable with this. #endif #ifdef CONFIG_USB_NET1080 diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c index d879f82a5029..d80cb3377839 100644 --- a/drivers/usb/storage/protocol.c +++ b/drivers/usb/storage/protocol.c @@ -54,10 +54,27 @@ * Helper routines ***********************************************************************/ -/* Fix-up the return data from an INQUIRY command to show +static void * +find_data_location(Scsi_Cmnd *srb) { + if (srb->use_sg) { + /* + * This piece of code only works if the first page is + * big enough to hold more than 3 bytes -- which is + * _very_ likely. + */ + struct scatterlist *sg; + + sg = (struct scatterlist *) srb->request_buffer; + return (void *) page_address(sg[0].page) + sg[0].offset; + } else + return (void *) srb->request_buffer; +} + +/* + * Fix-up the return data from an INQUIRY command to show * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us */ -void fix_inquiry_data(Scsi_Cmnd *srb) +static void fix_inquiry_data(Scsi_Cmnd *srb) { unsigned char *data_ptr; @@ -65,24 +82,43 @@ void fix_inquiry_data(Scsi_Cmnd *srb) if (srb->cmnd[0] != INQUIRY) return; - US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2\n"); + data_ptr = find_data_location(srb); - /* find the location of the data */ - if (srb->use_sg) { - /* this piece of code only works if the first page is big enough to - * hold more than 3 bytes -- which is _very_ likely - */ - struct scatterlist *sg; + if ((data_ptr[2] & 7) == 2) + return; - sg = (struct scatterlist *) srb->request_buffer; - data_ptr = (unsigned char *) page_address(sg[0].page) + sg[0].offset; - } else - data_ptr = (unsigned char *)srb->request_buffer; + US_DEBUGP("Fixing INQUIRY data to show SCSI rev 2 - was %d\n", + data_ptr[2] & 7); /* Change the SCSI revision number */ data_ptr[2] = (data_ptr[2] & ~7) | 2; } +/* + * Fix-up the return data from a READ CAPACITY command. My Feiya reader + * returns a value that is 1 too large. + */ +static void fix_read_capacity(Scsi_Cmnd *srb) +{ + unsigned char *dp; + unsigned long capacity; + + /* verify that it's a READ CAPACITY command */ + if (srb->cmnd[0] != READ_CAPACITY) + return; + + dp = find_data_location(srb); + + capacity = (dp[0]<<24) + (dp[1]<<16) + (dp[2]<<8) + (dp[3]); + US_DEBUGP("US: Fixing capacity: from %ld to %ld\n", + capacity+1, capacity); + capacity--; + dp[0] = (capacity >> 24); + dp[1] = (capacity >> 16); + dp[2] = (capacity >> 8); + dp[3] = (capacity); +} + /*********************************************************************** * Protocol routines ***********************************************************************/ @@ -346,8 +382,11 @@ void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us) if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SENSE)) usb_stor_scsiSense10to6(srb); - /* fix the INQUIRY data if necessary */ + /* Fix the INQUIRY data if necessary */ fix_inquiry_data(srb); + + /* Fix the READ CAPACITY result if necessary */ + if (us->flags & US_FL_FIX_CAPACITY) + fix_read_capacity(srb); } } - diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 872d8773c5ac..70cac2634164 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -883,6 +883,9 @@ void usb_stor_abort_transport(struct us_data *us) usb_stor_CBI_irq(us->irq_urb); } + /* Wait for the aborted command to finish */ + wait_for_completion(&us->notify); + /* Reacquire the lock */ scsi_lock(us->srb->host); } diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index f1e2eb3071f3..abb117bfe6e4 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -310,6 +310,13 @@ UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001, US_FL_MODE_XLATE ), #endif +/* Reported by Blake Matheny <bmatheny@purdue.edu> */ +UNUSUAL_DEV( 0x05dc, 0xb002, 0x0000, 0x0113, + "Lexar", + "USB CF Reader", + US_SC_SCSI, US_PR_BULK, NULL, + US_FL_FIX_INQUIRY ), + /* Reported by Carlos Villegas <cav@uniscope.co.jp> * This device needs an INQUIRY of exactly 36-bytes to function. * That is the only reason this entry is needed. @@ -507,6 +514,13 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009, US_SC_8070, US_PR_CB, NULL, US_FL_FIX_INQUIRY ), +/* aeb */ +UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, + "Feiya", + "5-in-1 Card Reader", + US_SC_SCSI, US_PR_BULK, NULL, + US_FL_FIX_CAPACITY ), + UNUSUAL_DEV( 0x097a, 0x0001, 0x0000, 0x0001, "Minds@Work", "Digital Wallet", diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 84a72fde8a75..67d969a7fa99 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -440,8 +440,14 @@ static int usb_stor_control_thread(void * __us) /* Most USB devices can't handle START_STOP. But we * need something for media-change, so we'll use TUR * instead. + * + * We specifically allow this command through if either: + * (a) it's a load/eject command (cmnd[4] & 2) + * (b) it's a multi-target unit (i.e. legacy SCSI adaptor) */ - else if (us->srb->cmnd[0] == START_STOP) { + else if (us->srb->cmnd[0] == START_STOP && + !(us->srb->cmnd[4] & 2) && + !(us->flags & US_FL_SCM_MULT_TARG)) { unsigned char saved_cdb[16]; /* largest SCSI-III cmd */ __u8 old_cmd_len; diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 0418d92651aa..19ecbe4b898e 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -102,6 +102,7 @@ struct us_unusual_dev { #define US_FL_IGNORE_SER 0x00000010 /* Ignore the serial number given */ #define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */ #define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs fixing */ +#define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */ #define US_FL_DEV_ATTACHED 0x00010000 /* is the device attached? */ #define US_FLIDX_IP_WANTED 17 /* 0x00020000 is an IRQ expected? */ diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 4ee650d38e7c..c23edd0315b8 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h @@ -32,7 +32,7 @@ #define UDF_NAME_LEN 255 #define UDF_PATH_LEN 1023 -#define CURRENT_UTIME (xtime.tv_usec) +#define CURRENT_UTIME (xtime.tv_nsec / 1000) #define udf_file_entry_alloc_offset(inode)\ ((UDF_I_EXTENDED_FE(inode) ?\ diff --git a/fs/ufs/super.c b/fs/ufs/super.c index eda1ea41f86a..10f706b7f02d 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -605,7 +605,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) } again: - if (sb_set_blocksize(sb, block_size)) { + if (!sb_set_blocksize(sb, block_size)) { printk(KERN_ERR "UFS: failed to set blocksize\n"); goto failed; } diff --git a/include/asm-i386/mtrr.h b/include/asm-i386/mtrr.h index ff3ea870d0d6..f2727e61fe63 100644 --- a/include/asm-i386/mtrr.h +++ b/include/asm-i386/mtrr.h @@ -115,13 +115,6 @@ static __inline__ void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) {;} # endif -/* The following functions are for initialisation: don't use them! */ -extern int mtrr_init (void); -# if defined(CONFIG_SMP) && defined(CONFIG_MTRR) -extern void mtrr_init_boot_cpu (void); -extern void mtrr_init_secondary_cpu (void); -# endif - #endif #endif /* _LINUX_MTRR_H */ diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 9c619036dfb6..1bdcda4d36c8 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -354,11 +354,11 @@ void acpi_numa_arch_fixup(void); extern int acpi_mp_config; -#else /*!CONFIG_ACPI_BOOT*/ +#else #define acpi_mp_config 0 -#endif /*CONFIG_ACPI_BOOT*/ +#endif #ifdef CONFIG_ACPI_PCI diff --git a/include/linux/pci.h b/include/linux/pci.h index b82ec8e41174..79d909a8643a 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -634,7 +634,6 @@ void pci_insert_device(struct pci_dev *, struct pci_bus *); void pci_remove_device(struct pci_dev *); struct pci_driver *pci_dev_driver(const struct pci_dev *); const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev); -void pci_announce_device_to_drivers(struct pci_dev *); unsigned int pci_do_scan_bus(struct pci_bus *bus); struct pci_bus * pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr); diff --git a/include/linux/time.h b/include/linux/time.h index d9f9c6a340d8..088c52d09449 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -113,7 +113,7 @@ mktime (unsigned int year, unsigned int mon, )*60 + sec; /* finally seconds */ } -extern struct timeval xtime; +extern struct timespec xtime; #define CURRENT_TIME (xtime.tv_sec) diff --git a/include/linux/timex.h b/include/linux/timex.h index b82cbdc776f7..5b2b0ac18ae7 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h @@ -155,6 +155,28 @@ /* LATCH is used in the interval timer and ftape setup. */ #define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ +/* Suppose we want to devide two numbers NOM and DEN: NOM/DEN, the we can + * improve accuracy by shifting LSH bits, hence calculating: + * (NOM << LSH) / DEN + * This however means trouble for large NOM, because (NOM << LSH) may no + * longer fit in 32 bits. The following way of calculating this gives us + * some slack, under the following onditions: + * - (NOM / DEN) fits in (32 - LSH) bits. + * - (NOM % DEN) fits in (32 - LSH) bits. + */ +#define SH_DIV(NOM,DEN,LSH) ( ((NOM / DEN) << LSH) \ + + (((NOM % DEN) << LSH) + DEN / 2) / DEN) + +/* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */ +#define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8)) + +/* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */ +#define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) + +/* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ and */ +/* a value TUSEC for TICK_USEC (can be set bij adjtimex) */ +#define TICK_NSEC(TUSEC) (SH_DIV (TUSEC * USER_HZ * 1000, ACTHZ, 8)) + /* * syscall interface - used (mainly by NTP daemon) * to discipline kernel clock oscillator @@ -251,7 +273,8 @@ struct timex { * Note: maximum error = NTP synch distance = dispersion + delay / 2; * estimated error = NTP dispersion. */ -extern long tick; /* timer interrupt period */ +extern unsigned long tick_usec; /* USER_HZ period (usec) */ +extern unsigned long tick_nsec; /* ACTHZ period (nsec) */ extern int tickadj; /* amount of adjustment per tick */ /* diff --git a/init/main.c b/init/main.c index 9aa3a0600960..b484d14df3a2 100644 --- a/init/main.c +++ b/init/main.c @@ -38,10 +38,6 @@ #include <asm/s390mach.h> #endif -#ifdef CONFIG_MTRR -# include <asm/mtrr.h> -#endif - #ifdef CONFIG_X86_LOCAL_APIC #include <asm/smp.h> #endif @@ -536,15 +532,6 @@ static int init(void * unused) */ child_reaper = current; -#if defined(CONFIG_MTRR) /* Do this after SMP initialization */ -/* - * We should probably create some architecture-dependent "fixup after - * everything is up" style function where this would belong better - * than in init/main.c.. - */ - mtrr_init(); -#endif - /* Sets up cpus_possible() */ smp_prepare_cpus(max_cpus); diff --git a/kernel/time.c b/kernel/time.c index edb7eb7b8b73..716e0bbe071a 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -82,7 +82,7 @@ asmlinkage long sys_stime(int * tptr) return -EFAULT; write_lock_irq(&xtime_lock); xtime.tv_sec = value; - xtime.tv_usec = 0; + xtime.tv_nsec = 0; last_time_offset = 0; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; @@ -231,7 +231,8 @@ int do_adjtimex(struct timex *txc) /* if the quartz is off by more than 10% something is VERY wrong ! */ if (txc->modes & ADJ_TICK) - if (txc->tick < 900000/HZ || txc->tick > 1100000/HZ) + if (txc->tick < 900000/USER_HZ || + txc->tick > 1100000/USER_HZ) return -EINVAL; write_lock_irq(&xtime_lock); @@ -344,13 +345,8 @@ int do_adjtimex(struct timex *txc) } /* STA_PLL || STA_PPSTIME */ } /* txc->modes & ADJ_OFFSET */ if (txc->modes & ADJ_TICK) { - /* if the quartz is off by more than 10% something is - VERY wrong ! */ - if (txc->tick < 900000/HZ || txc->tick > 1100000/HZ) { - result = -EINVAL; - goto leave; - } - tick = txc->tick; + tick_usec = txc->tick; + tick_nsec = TICK_NSEC(tick_usec); } } /* txc->modes */ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0 @@ -380,7 +376,7 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0 txc->constant = time_constant; txc->precision = time_precision; txc->tolerance = time_tolerance; - txc->tick = tick; + txc->tick = tick_usec; txc->ppsfreq = pps_freq; txc->jitter = pps_jitter >> PPS_AVG; txc->shift = pps_shift; diff --git a/kernel/timer.c b/kernel/timer.c index d4efe5823e94..3b4be840f931 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -33,10 +33,11 @@ struct kernel_stat kstat; * Timekeeping variables */ -long tick = (1000000 + HZ/2) / HZ; /* timer interrupt period */ +unsigned long tick_usec = TICK_USEC; /* ACTHZ period (usec) */ +unsigned long tick_nsec = TICK_NSEC(TICK_USEC); /* USER_HZ period (nsec) */ /* The current time */ -struct timeval xtime __attribute__ ((aligned (16))); +struct timespec xtime __attribute__ ((aligned (16))); /* Don't completely fail for HZ > 500. */ int tickadj = 500/HZ ? : 1; /* microsecs */ @@ -63,7 +64,6 @@ long time_adj; /* tick adjust (scaled 1 / HZ) */ long time_reftime; /* time at last adjustment (s) */ long time_adjust; -long time_adjust_step; unsigned long event; @@ -465,6 +465,8 @@ static void second_overflow(void) /* in the NTP reference this is called "hardclock()" */ static void update_wall_time_one_tick(void) { + long time_adjust_step; + if ( (time_adjust_step = time_adjust) != 0 ) { /* We are doing an adjtime thing. * @@ -483,21 +485,21 @@ static void update_wall_time_one_tick(void) /* Reduce by this step the amount of time left */ time_adjust -= time_adjust_step; } - xtime.tv_usec += tick + time_adjust_step; + xtime.tv_nsec += tick_nsec + time_adjust_step * 1000; /* * Advance the phase, once it gets to one microsecond, then * advance the tick more. */ time_phase += time_adj; if (time_phase <= -FINEUSEC) { - long ltemp = -time_phase >> SHIFT_SCALE; - time_phase += ltemp << SHIFT_SCALE; - xtime.tv_usec -= ltemp; + long ltemp = -time_phase >> (SHIFT_SCALE - 10); + time_phase += ltemp << (SHIFT_SCALE - 10); + xtime.tv_nsec -= ltemp; } else if (time_phase >= FINEUSEC) { - long ltemp = time_phase >> SHIFT_SCALE; - time_phase -= ltemp << SHIFT_SCALE; - xtime.tv_usec += ltemp; + long ltemp = time_phase >> (SHIFT_SCALE - 10); + time_phase -= ltemp << (SHIFT_SCALE - 10); + xtime.tv_nsec += ltemp; } } @@ -515,8 +517,8 @@ static void update_wall_time(unsigned long ticks) update_wall_time_one_tick(); } while (ticks); - if (xtime.tv_usec >= 1000000) { - xtime.tv_usec -= 1000000; + if (xtime.tv_nsec >= 1000000000) { + xtime.tv_nsec -= 1000000000; xtime.tv_sec++; second_overflow(); } |
