diff options
32 files changed, 1927 insertions, 1189 deletions
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index 129bbbb7d246..8b35ee23ed6a 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -161,7 +161,7 @@ KAO --> </sect1> <sect1><title>MTRR Handling</title> -!Earch/i386/kernel/mtrr.c +!Earch/i386/kernel/cpu/mtrr/main.c </sect1> <sect1><title>PCI Support Library</title> !Edrivers/pci/pci.c diff --git a/Documentation/filesystems/directory-locking b/Documentation/filesystems/directory-locking index 6d33a65a0837..a320ac2909e7 100644 --- a/Documentation/filesystems/directory-locking +++ b/Documentation/filesystems/directory-locking @@ -80,14 +80,14 @@ would have a contended child and we had assumed that no object is its own descendent. Moreover, there is exactly one cross-directory rename (see above). - Consider the object blocking the cross-directory rename. One of -its descendents is locked by cross-directory rename (otherwise we would again -have an infinite set of of contended objects). But that means that means -that cross-directory rename is taking locks out of order. Due to (2) the -order hadn't changed since we had acquired filesystem lock. But locking -rules for cross-directory rename guarantee that we do not try to acquire -lock on descendent before the lock on ancestor. Contradiction. I.e. -deadlock is impossible. Q.E.D. + Consider the object blocking the cross-directory rename. One +of its descendents is locked by cross-directory rename (otherwise we +would again have an infinite set of of contended objects). But that +means that cross-directory rename is taking locks out of order. Due +to (2) the order hadn't changed since we had acquired filesystem lock. +But locking rules for cross-directory rename guarantee that we do not +try to acquire lock on descendent before the lock on ancestor. +Contradiction. I.e. deadlock is impossible. Q.E.D. These operations are guaranteed to avoid loop creation. Indeed, diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index b5e03c88e291..6173c392d58f 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -69,7 +69,7 @@ Locking change: ->s_vfs_rename_sem is taken only by cross-directory renames. Most likely there is no need to change anything, but if you relied on global exclusion between renames for some internal purpose - you need to change your internal locking. Otherwise exclusion warranties remain the -same (i.e. parents are victim are locked, etc.). +same (i.e. parents and victim are locked, etc.). --- [informational] diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c index ff98d996d336..6aa1e33becaf 100644 --- a/arch/i386/kernel/cpu/intel.c +++ b/arch/i386/kernel/cpu/intel.c @@ -156,6 +156,7 @@ static void __init init_intel(struct cpuinfo_x86 *c) } #endif + get_model_name(c); if (c->cpuid_level > 1) { /* supports eax=2 call */ 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/drivers/char/toshiba.c b/drivers/char/toshiba.c index 60c5d71b88fa..71b2cf809c3e 100644 --- a/drivers/char/toshiba.c +++ b/drivers/char/toshiba.c @@ -114,11 +114,10 @@ static int tosh_fn_status(void) if (tosh_fn!=0) { scan = inb(tosh_fn); } else { - save_flags(flags); - cli(); + local_irq_save(flags); outb(0x8e, 0xe4); scan = inb(0xe5); - restore_flags(flags); + local_irq_restore(flags); } return (int) scan; @@ -141,35 +140,32 @@ static int tosh_emulate_fan(SMMRegisters *regs) if (tosh_id==0xfccb) { if (eax==0xfe00) { /* fan status */ - save_flags(flags); - cli(); + local_irq_save(flags); outb(0xbe, 0xe4); al = inb(0xe5); - restore_flags(flags); + local_irq_restore(flags); regs->eax = 0x00; regs->ecx = (unsigned int) (al & 0x01); } if ((eax==0xff00) && (ecx==0x0000)) { /* fan off */ - save_flags(flags); - cli(); + local_irq_save(flags); outb(0xbe, 0xe4); al = inb(0xe5); outb(0xbe, 0xe4); outb (al | 0x01, 0xe5); - restore_flags(flags); + local_irq_restore(flags); regs->eax = 0x00; regs->ecx = 0x00; } if ((eax==0xff00) && (ecx==0x0001)) { /* fan on */ - save_flags(flags); - cli(); + local_irq_save(flags); outb(0xbe, 0xe4); al = inb(0xe5); outb(0xbe, 0xe4); outb(al & 0xfe, 0xe5); - restore_flags(flags); + local_irq_restore(flags); regs->eax = 0x00; regs->ecx = 0x01; } @@ -180,33 +176,30 @@ static int tosh_emulate_fan(SMMRegisters *regs) if (tosh_id==0xfccc) { if (eax==0xfe00) { /* fan status */ - save_flags(flags); - cli(); + local_irq_save(flags); outb(0xe0, 0xe4); al = inb(0xe5); - restore_flags(flags); + local_irq_restore(flags); regs->eax = 0x00; regs->ecx = al & 0x01; } if ((eax==0xff00) && (ecx==0x0000)) { /* fan off */ - save_flags(flags); - cli(); + local_irq_save(flags); outb(0xe0, 0xe4); al = inb(0xe5); outw(0xe0 | ((al & 0xfe) << 8), 0xe4); - restore_flags(flags); + local_irq_restore(flags); regs->eax = 0x00; regs->ecx = 0x00; } if ((eax==0xff00) && (ecx==0x0001)) { /* fan on */ - save_flags(flags); - cli(); + local_irq_save(flags); outb(0xe0, 0xe4); al = inb(0xe5); outw(0xe0 | ((al | 0x01) << 8), 0xe4); - restore_flags(flags); + local_irq_restore(flags); regs->eax = 0x00; regs->ecx = 0x01; } 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/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/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/init/main.c b/init/main.c index d303935d14cd..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 @@ -490,15 +486,6 @@ static void __init do_initcalls(void) */ static void __init do_basic_setup(void) { -#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 - #ifdef CONFIG_SYSCTL sysctl_init(); #endif diff --git a/kernel/signal.c b/kernel/signal.c index 5ca0ca83eb2f..1d1da8ef89ea 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1220,6 +1220,7 @@ int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs) #endif +EXPORT_SYMBOL(recalc_sigpending); EXPORT_SYMBOL(dequeue_signal); EXPORT_SYMBOL(flush_signals); EXPORT_SYMBOL(force_sig); |
