Commit 38908d74 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://linux-acpi.bkbits.net/linux-acpi

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents 03e691ed 8a0f08e2
...@@ -110,12 +110,54 @@ cyrix_get_free_region(unsigned long base, unsigned long size) ...@@ -110,12 +110,54 @@ cyrix_get_free_region(unsigned long base, unsigned long size)
return -ENOSPC; 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, static void cyrix_set_arr(unsigned int reg, unsigned long base,
unsigned long size, mtrr_type type) unsigned long size, mtrr_type type)
{ {
unsigned char arr, arr_type, arr_size; unsigned char arr, arr_type, arr_size;
u32 cr0, ccr3;
u32 cr4 = 0;
arr = CX86_ARR_BASE + (reg << 1) + reg; /* avoid multiplication by 3 */ 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, ...@@ -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) */ prepare_set();
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);
base <<= PAGE_SHIFT; base <<= PAGE_SHIFT;
setCx86(arr, ((unsigned char *) &base)[3]); setCx86(arr, ((unsigned char *) &base)[3]);
...@@ -183,18 +208,7 @@ static void cyrix_set_arr(unsigned int reg, unsigned long base, ...@@ -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(arr + 2, (((unsigned char *) &base)[1]) | arr_size);
setCx86(CX86_RCR_BASE + reg, arr_type); setCx86(CX86_RCR_BASE + reg, arr_type);
/* Flush caches and TLBs */ post_set();
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);
} }
typedef struct { typedef struct {
...@@ -210,31 +224,11 @@ arr_state_t arr_state[8] __initdata = { ...@@ -210,31 +224,11 @@ arr_state_t arr_state[8] __initdata = {
unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 }; unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 };
static void __init static void cyrix_set_all(void)
cyrix_arr_init_secondary(void)
{ {
int i; 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 prepare_set();
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);
/* the CCRs are not contiguous */ /* the CCRs are not contiguous */
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
...@@ -245,18 +239,7 @@ cyrix_arr_init_secondary(void) ...@@ -245,18 +239,7 @@ cyrix_arr_init_secondary(void)
cyrix_set_arr(i, arr_state[i].base, cyrix_set_arr(i, arr_state[i].base,
arr_state[i].size, arr_state[i].type); arr_state[i].size, arr_state[i].type);
/* Flush caches and TLBs */ post_set();
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);
} }
/* /*
...@@ -361,7 +344,7 @@ cyrix_arr_init(void) ...@@ -361,7 +344,7 @@ cyrix_arr_init(void)
static struct mtrr_ops cyrix_mtrr_ops = { static struct mtrr_ops cyrix_mtrr_ops = {
.vendor = X86_VENDOR_CYRIX, .vendor = X86_VENDOR_CYRIX,
.init = cyrix_arr_init, .init = cyrix_arr_init,
.init_secondary = cyrix_arr_init_secondary, .set_all = cyrix_set_all,
.set = cyrix_set_arr, .set = cyrix_set_arr,
.get = cyrix_get_arr, .get = cyrix_get_arr,
.get_free_region = cyrix_get_free_region, .get_free_region = cyrix_get_free_region,
......
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/mtrr.h> #include <asm/mtrr.h>
...@@ -6,6 +8,90 @@ ...@@ -6,6 +8,90 @@
#include <asm/cpufeature.h> #include <asm/cpufeature.h>
#include "mtrr.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) int generic_get_free_region(unsigned long base, unsigned long size)
/* [SUMMARY] Get a free MTRR. /* [SUMMARY] Get a free MTRR.
...@@ -55,23 +141,104 @@ void generic_get_mtrr(unsigned int reg, unsigned long *base, ...@@ -55,23 +141,104 @@ void generic_get_mtrr(unsigned int reg, unsigned long *base,
*type = base_lo & 0xff; *type = base_lo & 0xff;
} }
void generic_set_mtrr(unsigned int reg, unsigned long base, static int __init set_fixed_ranges(mtrr_type * frs)
unsigned long size, mtrr_type type) {
/* [SUMMARY] Set variable MTRR register on the local CPU. unsigned long *p = (unsigned long *) frs;
<reg> The register to set. int changed = FALSE;
<base> The base address of the region. int i;
<size> The size of the region. If this is 0 the region is disabled. unsigned long lo, hi;
<type> The type of the region.
<do_safe> If TRUE, do the change safely. If FALSE, safety measures should rdmsr(MTRRfix64K_00000_MSR, lo, hi);
be done externally. if (p[0] != lo || p[1] != hi) {
[RETURNS] Nothing. 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; unsigned int i;
u32 deftype_lo, deftype_hi; unsigned long change_mask = 0;
static spinlock_t set_atomicity_lock = SPIN_LOCK_UNLOCKED;
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) */ /* Save value of CR4 and clear Page Global Enable (bit 7) */
if ( cpu_has_pge ) { if ( cpu_has_pge ) {
cr4 = read_cr4(); cr4 = read_cr4();
...@@ -90,18 +257,10 @@ void generic_set_mtrr(unsigned int reg, unsigned long base, ...@@ -90,18 +257,10 @@ void generic_set_mtrr(unsigned int reg, unsigned long base,
/* Disable MTRRs, and set the default type to uncached */ /* Disable MTRRs, and set the default type to uncached */
wrmsr(MTRRdefType_MSR, deftype_lo & 0xf300UL, deftype_hi); wrmsr(MTRRdefType_MSR, deftype_lo & 0xf300UL, deftype_hi);
}
if (size == 0) { static void post_set(void)
/* 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));
}
/* Flush caches and TLBs */ /* Flush caches and TLBs */
wbinvd(); wbinvd();
...@@ -114,7 +273,57 @@ void generic_set_mtrr(unsigned int reg, unsigned long base, ...@@ -114,7 +273,57 @@ void generic_set_mtrr(unsigned int reg, unsigned long base,
/* Restore value of CR4 */ /* Restore value of CR4 */
if ( cpu_has_pge ) if ( cpu_has_pge )
write_cr4(cr4); 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) int generic_validate_add_page(unsigned long base, unsigned long size, unsigned int type)
...@@ -178,7 +387,7 @@ int positive_have_wrcomb(void) ...@@ -178,7 +387,7 @@ int positive_have_wrcomb(void)
*/ */
struct mtrr_ops generic_mtrr_ops = { struct mtrr_ops generic_mtrr_ops = {
.use_intel_if = 1, .use_intel_if = 1,
.init_secondary = generic_init_secondary, .set_all = generic_set_all,
.get = generic_get_mtrr, .get = generic_get_mtrr,
.get_free_region = generic_get_free_region, .get_free_region = generic_get_free_region,
.set = generic_set_mtrr, .set = generic_set_mtrr,
......
...@@ -163,8 +163,11 @@ static void ipi_handler(void *info) ...@@ -163,8 +163,11 @@ static void ipi_handler(void *info)
} }
/* The master has cleared me to execute */ /* The master has cleared me to execute */
if (data->smp_reg != ~0UL)
mtrr_if->set(data->smp_reg, data->smp_base, mtrr_if->set(data->smp_reg, data->smp_base,
data->smp_size, data->smp_type); data->smp_size, data->smp_type);
else
mtrr_if->set_all();
atomic_dec(&data->count); atomic_dec(&data->count);
while(atomic_read(&data->gate)) { while(atomic_read(&data->gate)) {
...@@ -243,6 +246,14 @@ static void set_mtrr(unsigned int reg, unsigned long base, ...@@ -243,6 +246,14 @@ static void set_mtrr(unsigned int reg, unsigned long base,
atomic_set(&data.gate,1); atomic_set(&data.gate,1);
/* do our MTRR business */ /* do our MTRR business */
/* 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); mtrr_if->set(reg,base,size,type);
/* wait for the others */ /* wait for the others */
...@@ -530,6 +541,20 @@ static void __init init_ifs(void) ...@@ -530,6 +541,20 @@ static void __init init_ifs(void)
centaur_init_mtrr(); 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 * mtrr_init - initialie mtrrs on the boot CPU
* *
...@@ -537,7 +562,7 @@ static void __init init_ifs(void) ...@@ -537,7 +562,7 @@ static void __init init_ifs(void)
* initialized (i.e. before smp_init()). * initialized (i.e. before smp_init()).
* *
*/ */
int __init mtrr_init(void) static int __init mtrr_init(void)
{ {
init_ifs(); init_ifs();
...@@ -608,21 +633,15 @@ int __init mtrr_init(void) ...@@ -608,21 +633,15 @@ int __init mtrr_init(void)
break; break;
} }
} }
printk("mtrr: v%s\n",MTRR_VERSION);
if (mtrr_if) { if (mtrr_if) {
set_num_var_ranges(); set_num_var_ranges();
if (use_intel()) {
/* Only for Intel MTRRs */
get_mtrr_state();
}
init_table(); 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; return mtrr_if ? -ENXIO : 0;
} }
//subsys_initcall(mtrr_init); core_initcall(mtrr_init);
...@@ -38,9 +38,10 @@ struct mtrr_ops { ...@@ -38,9 +38,10 @@ struct mtrr_ops {
u32 vendor; u32 vendor;
u32 use_intel_if; u32 use_intel_if;
void (*init)(void); void (*init)(void);
void (*init_secondary)(void);
void (*set)(unsigned int reg, unsigned long base, void (*set)(unsigned int reg, unsigned long base,
unsigned long size, mtrr_type type); unsigned long size, mtrr_type type);
void (*set_all)(void);
void (*get)(unsigned int reg, unsigned long *base, void (*get)(unsigned int reg, unsigned long *base,
unsigned long *size, mtrr_type * type); unsigned long *size, mtrr_type * type);
int (*get_free_region) (unsigned long base, unsigned long size); int (*get_free_region) (unsigned long base, unsigned long size);
......
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/mtrr.h> #include <asm/mtrr.h>
#include <asm/msr.h> #include <asm/msr.h>
#include "mtrr.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 */ /* Put the processor into a state where MTRRs can be safely set */
void set_mtrr_prepare_save(struct set_mtrr_context *ctxt) void set_mtrr_prepare_save(struct set_mtrr_context *ctxt)
...@@ -246,93 +76,3 @@ void set_mtrr_done(struct set_mtrr_context *ctxt) ...@@ -246,93 +76,3 @@ void set_mtrr_done(struct set_mtrr_context *ctxt)
local_irq_restore(ctxt->flags); 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);
...@@ -45,7 +45,6 @@ ...@@ -45,7 +45,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mc146818rtc.h> #include <linux/mc146818rtc.h>
#include <asm/mtrr.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/smpboot.h> #include <asm/smpboot.h>
...@@ -403,12 +402,6 @@ void __init smp_callin(void) ...@@ -403,12 +402,6 @@ void __init smp_callin(void)
local_irq_enable(); local_irq_enable();
#ifdef CONFIG_MTRR
/*
* Must be done before calibration delay is computed
*/
mtrr_init_secondary_cpu ();
#endif
/* /*
* Get our bogomips. * Get our bogomips.
*/ */
......
...@@ -292,16 +292,14 @@ struct controller { ...@@ -292,16 +292,14 @@ struct controller {
struct pci_resource *io_head; struct pci_resource *io_head;
struct pci_resource *bus_head; struct pci_resource *bus_head;
struct pci_dev *pci_dev; 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_entry;
struct proc_dir_entry* proc_entry2; struct proc_dir_entry* proc_entry2;
struct event_info event_queue[10]; struct event_info event_queue[10];
struct slot *slot; struct slot *slot;
u8 next_event; u8 next_event;
u8 interrupt; u8 interrupt;
u8 bus; u8 bus; /* bus number for the pci hotplug controller */
u8 device;
u8 function;
u8 rev; u8 rev;
u8 slot_device_offset; u8 slot_device_offset;
u8 first_slot; u8 first_slot;
...@@ -695,7 +693,8 @@ static inline int cpq_get_latch_status (struct controller *ctrl, struct slot *sl ...@@ -695,7 +693,8 @@ static inline int cpq_get_latch_status (struct controller *ctrl, struct slot *sl
return 1; return 1;
hp_slot = slot->device - ctrl->slot_device_offset; 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)); 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) ...@@ -733,7 +732,7 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl)
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
int retval = 0; int retval = 0;
dbg(__FUNCTION__" - start\n"); dbg("%s - start\n", __FUNCTION__);
add_wait_queue(&ctrl->queue, &wait); add_wait_queue(&ctrl->queue, &wait);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
/* Sleep for up to 1 second to wait for the LED to change. */ /* 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) ...@@ -743,7 +742,7 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl)
if (signal_pending(current)) if (signal_pending(current))
retval = -EINTR; retval = -EINTR;
dbg(__FUNCTION__" - end\n"); dbg("%s - end\n", __FUNCTION__);
return retval; return retval;
} }
......
...@@ -314,7 +314,7 @@ static int ctrl_slot_setup (struct controller * ctrl, void *smbios_start, void * ...@@ -314,7 +314,7 @@ static int ctrl_slot_setup (struct controller * ctrl, void *smbios_start, void *
void *slot_entry= NULL; void *slot_entry= NULL;
int result; int result;
dbg(__FUNCTION__"\n"); dbg("%s\n", __FUNCTION__);
tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR); tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);
...@@ -467,7 +467,7 @@ static int ctrl_slot_cleanup (struct controller * ctrl) ...@@ -467,7 +467,7 @@ static int ctrl_slot_cleanup (struct controller * ctrl)
// //
// Output: SUCCESS or FAILURE // 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; struct irq_routing_table *PCIIRQRoutingInfoLength;
u32 work; u32 work;
...@@ -476,7 +476,7 @@ static int get_slot_mapping (struct pci_ops *ops, u8 bus_num, u8 dev_num, u8 *sl ...@@ -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; 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; bridgeSlot = 0xFF;
...@@ -490,7 +490,6 @@ static int get_slot_mapping (struct pci_ops *ops, u8 bus_num, u8 dev_num, u8 *sl ...@@ -490,7 +490,6 @@ static int get_slot_mapping (struct pci_ops *ops, u8 bus_num, u8 dev_num, u8 *sl
return -1; return -1;
} }
for (loop = 0; loop < len; ++loop) { for (loop = 0; loop < len; ++loop) {
tbus = PCIIRQRoutingInfoLength->slots[loop].bus; tbus = PCIIRQRoutingInfoLength->slots[loop].bus;
tdevice = PCIIRQRoutingInfoLength->slots[loop].devfn >> 3; 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 ...@@ -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)) { if ((tbus == bus_num) && (tdevice == dev_num)) {
*slot = tslot; *slot = tslot;
if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength ); if (PCIIRQRoutingInfoLength != NULL)
kfree(PCIIRQRoutingInfoLength);
return 0; return 0;
} else { } else {
// Didn't get a match on the target PCI device. Check if the // 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 ...@@ -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 // 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 // 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. // 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) { 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. // See if bridge's secondary bus matches target bus.
if (((work >> 8) & 0x000000FF) == (long) bus_num) { if (((work >> 8) & 0x000000FF) == (long) bus_num) {
bridgeSlot = tslot; bridgeSlot = tslot;
...@@ -521,7 +522,6 @@ static int get_slot_mapping (struct pci_ops *ops, u8 bus_num, u8 dev_num, u8 *sl ...@@ -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 // 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 // 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 // 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) ...@@ -592,7 +592,7 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
if (slot == NULL) if (slot == NULL)
return -ENODEV; return -ENODEV;
dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
ctrl = slot->ctrl; ctrl = slot->ctrl;
if (ctrl == NULL) if (ctrl == NULL)
...@@ -627,7 +627,7 @@ static int process_SI (struct hotplug_slot *hotplug_slot) ...@@ -627,7 +627,7 @@ static int process_SI (struct hotplug_slot *hotplug_slot)
if (slot == NULL) if (slot == NULL)
return -ENODEV; return -ENODEV;
dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
ctrl = slot->ctrl; ctrl = slot->ctrl;
if (ctrl == NULL) if (ctrl == NULL)
...@@ -667,7 +667,7 @@ static int process_SS (struct hotplug_slot *hotplug_slot) ...@@ -667,7 +667,7 @@ static int process_SS (struct hotplug_slot *hotplug_slot)
if (slot == NULL) if (slot == NULL)
return -ENODEV; return -ENODEV;
dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
ctrl = slot->ctrl; ctrl = slot->ctrl;
if (ctrl == NULL) if (ctrl == NULL)
...@@ -695,7 +695,7 @@ static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value) ...@@ -695,7 +695,7 @@ static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value)
struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
struct controller *ctrl; struct controller *ctrl;
dbg(__FUNCTION__"\n"); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
if (slot == NULL) if (slot == NULL)
return -ENODEV; return -ENODEV;
...@@ -716,7 +716,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -716,7 +716,7 @@ static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
if (slot == NULL) if (slot == NULL)
return -ENODEV; return -ENODEV;
dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
ctrl = slot->ctrl; ctrl = slot->ctrl;
if (ctrl == NULL) if (ctrl == NULL)
...@@ -734,7 +734,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -734,7 +734,7 @@ static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
if (slot == NULL) if (slot == NULL)
return -ENODEV; return -ENODEV;
dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
ctrl = slot->ctrl; ctrl = slot->ctrl;
if (ctrl == NULL) if (ctrl == NULL)
...@@ -752,7 +752,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -752,7 +752,7 @@ static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
if (slot == NULL) if (slot == NULL)
return -ENODEV; return -ENODEV;
dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
ctrl = slot->ctrl; ctrl = slot->ctrl;
if (ctrl == NULL) if (ctrl == NULL)
...@@ -771,7 +771,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) ...@@ -771,7 +771,7 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
if (slot == NULL) if (slot == NULL)
return -ENODEV; return -ENODEV;
dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
ctrl = slot->ctrl; ctrl = slot->ctrl;
if (ctrl == NULL) if (ctrl == NULL)
...@@ -820,7 +820,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -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 // 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); rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
if (rc) { if (rc) {
err(__FUNCTION__" : pci_read_config_word failed\n"); err("%s : pci_read_config_word failed\n", __FUNCTION__);
return rc; return rc;
} }
dbg("Subsystem Vendor ID: %x\n", subsystem_vid); 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) ...@@ -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); ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL);
if (!ctrl) { if (!ctrl) {
err(__FUNCTION__" : out of memory\n"); err("%s : out of memory\n", __FUNCTION__);
return -ENOMEM; return -ENOMEM;
} }
memset(ctrl, 0, sizeof(struct controller)); memset(ctrl, 0, sizeof(struct controller));
rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid); rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystem_deviceid);
if (rc) { if (rc) {
err(__FUNCTION__" : pci_read_config_word failed\n"); err("%s : pci_read_config_word failed\n", __FUNCTION__);
goto err_free_ctrl; goto err_free_ctrl;
} }
...@@ -991,12 +991,20 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -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"); dbg (" pcix_support %s\n", ctrl->pcix_support == 0 ? "not supported" : "supported");
ctrl->pci_dev = pdev; 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->bus = pdev->bus->number;
ctrl->device = PCI_SLOT(pdev->devfn);
ctrl->function = PCI_FUNC(pdev->devfn);
ctrl->rev = rev; 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_MUTEX(&ctrl->crit_sect);
init_waitqueue_head(&ctrl->queue); init_waitqueue_head(&ctrl->queue);
...@@ -1004,7 +1012,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -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 */ /* initialize our threads if they haven't already been started up */
rc = one_time_init(); rc = one_time_init();
if (rc) { if (rc) {
goto err_free_ctrl; goto err_free_bus;
} }
dbg("pdev = %p\n", pdev); dbg("pdev = %p\n", pdev);
...@@ -1015,7 +1023,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -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)) { pci_resource_len(pdev, 0), MY_NAME)) {
err("cannot reserve MMIO region\n"); err("cannot reserve MMIO region\n");
rc = -ENOMEM; rc = -ENOMEM;
goto err_free_ctrl; goto err_free_bus;
} }
ctrl->hpc_reg = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); 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) ...@@ -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" // in this case it will always be called for the "base"
// bus/dev/func of a slot. // bus/dev/func of a slot.
// CS: this is leveraging the PCIIRQ routing code from the kernel (pci-pc.c: get_irq_routing_table) // 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); dbg("get_slot_mapping: first_slot = %d, returned = %d\n", ctrl->first_slot, rc);
if (rc) { if (rc) {
err(msg_initialization_err, rc); err(msg_initialization_err, rc);
...@@ -1053,7 +1061,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -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 // Store PCI Config Space for all devices on this bus
rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK)); rc = cpqhp_save_config(ctrl, ctrl->bus, readb(ctrl->hpc_reg + SLOT_MASK));
if (rc) { 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; goto err_iounmap;
} }
...@@ -1080,7 +1088,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -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); rc = ctrl_slot_setup(ctrl, smbios_start, smbios_table);
if (rc) { if (rc) {
err(msg_initialization_err, 6); 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; goto err_iounmap;
} }
...@@ -1188,6 +1196,8 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1188,6 +1196,8 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
iounmap(ctrl->hpc_reg); iounmap(ctrl->hpc_reg);
err_free_mem_region: err_free_mem_region:
release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
err_free_bus:
kfree(ctrl->pci_bus);
err_free_ctrl: err_free_ctrl:
kfree(ctrl); kfree(ctrl);
return rc; return rc;
...@@ -1328,6 +1338,8 @@ static void unload_cpqphpd(void) ...@@ -1328,6 +1338,8 @@ static void unload_cpqphpd(void)
kfree(tres); kfree(tres);
} }
kfree (ctrl->pci_bus);
tctrl = ctrl; tctrl = ctrl;
ctrl = ctrl->next; ctrl = ctrl->next;
kfree(tctrl); kfree(tctrl);
......
This diff is collapsed.
...@@ -161,7 +161,7 @@ static int check_for_compaq_ROM (void *rom_start) ...@@ -161,7 +161,7 @@ static int check_for_compaq_ROM (void *rom_start)
(temp6 == 'Q')) { (temp6 == 'Q')) {
result = 1; result = 1;
} }
dbg (__FUNCTION__" - returned %d\n", result); dbg ("%s - returned %d\n", __FUNCTION__, result);
return result; return result;
} }
...@@ -286,12 +286,12 @@ static u32 store_HRT (void *rom_start) ...@@ -286,12 +286,12 @@ static u32 store_HRT (void *rom_start)
return(rc); return(rc);
// The device Number // 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) if (rc)
return(rc); return(rc);
// The function Number // 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) if (rc)
return(rc); return(rc);
...@@ -479,8 +479,9 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl) ...@@ -479,8 +479,9 @@ int compaq_nvram_load (void *rom_start, struct controller *ctrl)
device = p_ev_ctrl->device; device = p_ev_ctrl->device;
function = p_ev_ctrl->function; function = p_ev_ctrl->function;
while ((bus != ctrl->bus) || (device != ctrl->device) while ((bus != ctrl->bus) ||
|| (function != ctrl->function)) { (device != PCI_SLOT(ctrl->pci_dev->devfn)) ||
(function != PCI_FUNC(ctrl->pci_dev->devfn))) {
nummem = p_ev_ctrl->mem_avail; nummem = p_ev_ctrl->mem_avail;
numpmem = p_ev_ctrl->p_mem_avail; numpmem = p_ev_ctrl->p_mem_avail;
numio = p_ev_ctrl->io_avail; numio = p_ev_ctrl->io_avail;
......
This diff is collapsed.
...@@ -53,8 +53,9 @@ static int read_ctrl (char *buf, char **start, off_t offset, int len, int *eof, ...@@ -53,8 +53,9 @@ static int read_ctrl (char *buf, char **start, off_t offset, int len, int *eof,
*eof = 1; *eof = 1;
out += sprintf(out, "hot plug ctrl Info Page\n"); out += sprintf(out, "hot plug ctrl Info Page\n");
out += sprintf(out, "bus = %d, device = %d, function = %d\n",ctrl->bus, out += sprintf(out, "bus = %d, device = %d, function = %d\n",
ctrl->device, ctrl->function); ctrl->bus, PCI_SLOT(ctrl->pci_dev->devfn),
PCI_FUNC(ctrl->pci_dev->devfn));
out += sprintf(out, "Free resources: memory\n"); out += sprintf(out, "Free resources: memory\n");
index = 11; index = 11;
res = ctrl->mem_head; res = ctrl->mem_head;
...@@ -104,8 +105,9 @@ static int read_dev (char *buf, char **start, off_t offset, int len, int *eof, v ...@@ -104,8 +105,9 @@ static int read_dev (char *buf, char **start, off_t offset, int len, int *eof, v
*eof = 1; *eof = 1;
out += sprintf(out, "hot plug ctrl Info Page\n"); out += sprintf(out, "hot plug ctrl Info Page\n");
out += sprintf(out, "bus = %d, device = %d, function = %d\n",ctrl->bus, out += sprintf(out, "bus = %d, device = %d, function = %d\n",
ctrl->device, ctrl->function); ctrl->bus, PCI_SLOT(ctrl->pci_dev->devfn),
PCI_FUNC(ctrl->pci_dev->devfn));
slot=ctrl->slot; slot=ctrl->slot;
......
...@@ -39,7 +39,8 @@ extern int ibmphp_debug; ...@@ -39,7 +39,8 @@ extern int ibmphp_debug;
#else #else
#define MY_NAME THIS_MODULE->name #define MY_NAME THIS_MODULE->name
#endif #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 err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%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) #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
...@@ -121,6 +122,7 @@ struct scal_detail { ...@@ -121,6 +122,7 @@ struct scal_detail {
u8 port1_port_connect; u8 port1_port_connect;
u8 port2_node_connect; u8 port2_node_connect;
u8 port2_port_connect; u8 port2_port_connect;
u8 chassis_num;
// struct list_head scal_detail_list; // struct list_head scal_detail_list;
}; };
...@@ -139,9 +141,27 @@ struct rio_detail { ...@@ -139,9 +141,27 @@ struct rio_detail {
u8 port1_port_connect; u8 port1_port_connect;
u8 first_slot_num; u8 first_slot_num;
u8 status; 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 * * HPC DESCRIPTOR NODE *
...@@ -153,7 +173,6 @@ struct ebda_hpc_list { ...@@ -153,7 +173,6 @@ struct ebda_hpc_list {
short phys_addr; short phys_addr;
// struct list_head ebda_hpc_list; // struct list_head ebda_hpc_list;
}; };
/***************************************************************** /*****************************************************************
* IN HPC DATA STRUCTURE, THE ASSOCIATED SLOT AND BUS * * IN HPC DATA STRUCTURE, THE ASSOCIATED SLOT AND BUS *
* STRUCTURE * * STRUCTURE *
...@@ -195,6 +214,9 @@ struct wpeg_i2c_ctlr_access { ...@@ -195,6 +214,9 @@ struct wpeg_i2c_ctlr_access {
u8 i2c_addr; u8 i2c_addr;
}; };
#define HPC_DEVICE_ID 0x0246
#define HPC_SUBSYSTEM_ID 0x0247
#define HPC_PCI_OFFSET 0x40
/************************************************************************* /*************************************************************************
* RSTC DESCRIPTOR NODE * * RSTC DESCRIPTOR NODE *
*************************************************************************/ *************************************************************************/
...@@ -215,8 +237,9 @@ struct ebda_pci_rsrc { ...@@ -215,8 +237,9 @@ struct ebda_pci_rsrc {
u8 rsrc_type; u8 rsrc_type;
u8 bus_num; u8 bus_num;
u8 dev_fun; u8 dev_fun;
ulong start_addr; u32 start_addr;
ulong end_addr; u32 end_addr;
u8 marked; /* for NVRAM */
struct list_head ebda_pci_rsrc_list; struct list_head ebda_pci_rsrc_list;
}; };
...@@ -248,7 +271,7 @@ struct bus_info { ...@@ -248,7 +271,7 @@ struct bus_info {
***********************************************************/ ***********************************************************/
extern struct list_head ibmphp_ebda_pci_rsrc_head; extern struct list_head ibmphp_ebda_pci_rsrc_head;
extern struct list_head ibmphp_slot_head; extern struct list_head ibmphp_slot_head;
extern struct list_head ibmphp_res_head;
/*********************************************************** /***********************************************************
* FUNCTION PROTOTYPES * * FUNCTION PROTOTYPES *
***********************************************************/ ***********************************************************/
...@@ -263,6 +286,7 @@ extern void ibmphp_free_ebda_pci_rsrc_queue (void); ...@@ -263,6 +286,7 @@ extern void ibmphp_free_ebda_pci_rsrc_queue (void);
extern struct bus_info *ibmphp_find_same_bus_num (u32); extern struct bus_info *ibmphp_find_same_bus_num (u32);
extern int ibmphp_get_bus_index (u8); extern int ibmphp_get_bus_index (u8);
extern u16 ibmphp_get_total_controllers (void); extern u16 ibmphp_get_total_controllers (void);
extern int ibmphp_register_pci (void);
/* passed parameters */ /* passed parameters */
#define MEM 0 #define MEM 0
...@@ -669,7 +693,7 @@ extern void ibmphp_hpc_stop_poll_thread (void); ...@@ -669,7 +693,7 @@ extern void ibmphp_hpc_stop_poll_thread (void);
#define PCIX66 0x05 #define PCIX66 0x05
#define PCI66 0x04 #define PCI66 0x04
extern struct pci_ops *ibmphp_pci_root_ops; extern struct pci_bus *ibmphp_pci_bus;
/* Variables */ /* Variables */
...@@ -713,6 +737,7 @@ struct slot { ...@@ -713,6 +737,7 @@ struct slot {
struct controller { struct controller {
struct ebda_hpc_slot *slots; struct ebda_hpc_slot *slots;
struct ebda_hpc_bus *buses; 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 starting_slot_num; /* starting and ending slot #'s this ctrl controls*/
u8 ending_slot_num; u8 ending_slot_num;
u8 revision; u8 revision;
......
This diff is collapsed.
This diff is collapsed.
...@@ -107,8 +107,8 @@ static struct semaphore sem_exit; // make sure polling thread goes away ...@@ -107,8 +107,8 @@ static struct semaphore sem_exit; // make sure polling thread goes away
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// local function prototypes // local function prototypes
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static u8 ctrl_read (struct controller *, void *, u8); static u8 i2c_ctrl_read (struct controller *, void *, u8);
static u8 ctrl_write (struct controller *, void *, u8, u8); static u8 i2c_ctrl_write (struct controller *, void *, u8, u8);
static u8 hpc_writecmdtoindex (u8, u8); static u8 hpc_writecmdtoindex (u8, u8);
static u8 hpc_readcmdtoindex (u8, u8); static u8 hpc_readcmdtoindex (u8, u8);
static void get_hpc_access (void); static void get_hpc_access (void);
...@@ -142,12 +142,12 @@ void __init ibmphp_hpc_initvars (void) ...@@ -142,12 +142,12 @@ void __init ibmphp_hpc_initvars (void)
} }
/*---------------------------------------------------------------------- /*----------------------------------------------------------------------
* Name: ctrl_read * Name: i2c_ctrl_read
* *
* Action: read from HPC over I2C * 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; u8 status;
int i; int i;
...@@ -249,13 +249,13 @@ static u8 ctrl_read (struct controller *ctlr_ptr, void *WPGBbar, u8 index) ...@@ -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 * Action: write to HPC over I2C
* *
* Return 0 or error codes * 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; u8 rc;
void *wpg_addr; // base addr + offset void *wpg_addr; // base addr + offset
...@@ -351,6 +351,93 @@ static u8 ctrl_write (struct controller *ctlr_ptr, void *WPGBbar, u8 index, u8 c ...@@ -351,6 +351,93 @@ static u8 ctrl_write (struct controller *ctlr_ptr, void *WPGBbar, u8 index, u8 c
return (rc); 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() * Name: hpc_writecmdtoindex()
* *
...@@ -449,7 +536,7 @@ static u8 hpc_readcmdtoindex (u8 cmd, u8 index) ...@@ -449,7 +536,7 @@ static u8 hpc_readcmdtoindex (u8 cmd, u8 index)
*---------------------------------------------------------------------*/ *---------------------------------------------------------------------*/
int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus) int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
{ {
void *wpg_bbar; void *wpg_bbar = NULL;
struct controller *ctlr_ptr; struct controller *ctlr_ptr;
struct list_head *pslotlist; struct list_head *pslotlist;
u8 index, status; u8 index, status;
...@@ -491,6 +578,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus) ...@@ -491,6 +578,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// map physical address to logical address // map physical address to logical address
//-------------------------------------------------------------------- //--------------------------------------------------------------------
if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4))
wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE); wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE);
//-------------------------------------------------------------------- //--------------------------------------------------------------------
...@@ -569,7 +657,11 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus) ...@@ -569,7 +657,11 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// cleanup // 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 (); free_hpc_access ();
debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc); debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
...@@ -583,7 +675,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus) ...@@ -583,7 +675,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)
*---------------------------------------------------------------------*/ *---------------------------------------------------------------------*/
int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
{ {
void *wpg_bbar; void *wpg_bbar = NULL;
struct controller *ctlr_ptr; struct controller *ctlr_ptr;
u8 index, status; u8 index, status;
int busindex; int busindex;
...@@ -626,12 +718,13 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) ...@@ -626,12 +718,13 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// map physical address to logical address // map physical address to logical address
//-------------------------------------------------------------------- //--------------------------------------------------------------------
if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) {
wpg_bbar = ioremap (ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE); 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->ctlr_id, (ulong) (ctlr_ptr->u.wpeg_ctlr.wpegbbar), (ulong) wpg_bbar,
ctlr_ptr->u.wpeg_ctlr.i2c_addr); ctlr_ptr->u.wpeg_ctlr.i2c_addr);
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// check controller status before writing // check controller status before writing
//-------------------------------------------------------------------- //--------------------------------------------------------------------
...@@ -668,7 +761,10 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) ...@@ -668,7 +761,10 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
ctlr_ptr->status = status; ctlr_ptr->status = status;
} }
// cleanup // 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 (); free_hpc_access ();
debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc); debug_polling ("%s - Exit rc[%d]\n", __FUNCTION__, rc);
...@@ -701,6 +797,7 @@ void free_hpc_access (void) ...@@ -701,6 +797,7 @@ void free_hpc_access (void)
void ibmphp_lock_operations (void) void ibmphp_lock_operations (void)
{ {
down (&semOperations); down (&semOperations);
to_debug = TRUE;
} }
/*---------------------------------------------------------------------- /*----------------------------------------------------------------------
...@@ -710,6 +807,7 @@ void ibmphp_unlock_operations (void) ...@@ -710,6 +807,7 @@ void ibmphp_unlock_operations (void)
{ {
debug ("%s - Entry\n", __FUNCTION__); debug ("%s - Entry\n", __FUNCTION__);
up (&semOperations); up (&semOperations);
to_debug = FALSE;
debug ("%s - Exit\n", __FUNCTION__); debug ("%s - Exit\n", __FUNCTION__);
} }
...@@ -734,6 +832,9 @@ static void poll_hpc (void) ...@@ -734,6 +832,9 @@ static void poll_hpc (void)
debug ("%s - Entry\n", __FUNCTION__); debug ("%s - Entry\n", __FUNCTION__);
while (!ibmphp_shutdown) { while (!ibmphp_shutdown) {
if (ibmphp_shutdown)
break;
/* try to get the lock to do some kind of harware access */ /* try to get the lock to do some kind of harware access */
down (&semOperations); down (&semOperations);
...@@ -758,9 +859,9 @@ static void poll_hpc (void) ...@@ -758,9 +859,9 @@ static void poll_hpc (void)
} }
} }
} }
poll_state = POLL_SLOTS; ++poll_count;
poll_state = POLL_SLEEP;
break; break;
case POLL_SLOTS: case POLL_SLOTS:
list_for_each (pslotlist, &ibmphp_slot_head) { list_for_each (pslotlist, &ibmphp_slot_head) {
pslot = list_entry (pslotlist, struct slot, ibm_slot_list); pslot = list_entry (pslotlist, struct slot, ibm_slot_list);
...@@ -772,7 +873,6 @@ static void poll_hpc (void) ...@@ -772,7 +873,6 @@ static void poll_hpc (void)
|| (myslot.ext_status != pslot->ext_status)) || (myslot.ext_status != pslot->ext_status))
process_changeinstatus (pslot, &myslot); process_changeinstatus (pslot, &myslot);
} }
ctrl_count = 0x00; ctrl_count = 0x00;
list_for_each (pslotlist, &ibmphp_slot_head) { list_for_each (pslotlist, &ibmphp_slot_head) {
if (ctrl_count >= ibmphp_get_total_controllers()) if (ctrl_count >= ibmphp_get_total_controllers())
...@@ -787,29 +887,31 @@ static void poll_hpc (void) ...@@ -787,29 +887,31 @@ static void poll_hpc (void)
} }
} }
++poll_count; ++poll_count;
if (poll_count >= POLL_LATCH_CNT) {
poll_count = 0;
poll_state = POLL_SLEEP; poll_state = POLL_SLEEP;
}
break; break;
case POLL_SLEEP: case POLL_SLEEP:
/* don't sleep with a lock on the hardware */ /* don't sleep with a lock on the hardware */
up (&semOperations); up (&semOperations);
long_delay (POLL_INTERVAL_SEC * HZ); long_delay (POLL_INTERVAL_SEC * HZ);
if (ibmphp_shutdown)
break;
down (&semOperations); down (&semOperations);
if (poll_count >= POLL_LATCH_CNT) {
poll_count = 0;
poll_state = POLL_SLOTS;
} else
poll_state = POLL_LATCH_REGISTER; poll_state = POLL_LATCH_REGISTER;
break; break;
} }
/* give up the harware semaphore */ /* give up the harware semaphore */
up (&semOperations); up (&semOperations);
/* sleep for a short time just for good measure */ /* sleep for a short time just for good measure */
set_current_state (TASK_INTERRUPTIBLE); set_current_state (TASK_INTERRUPTIBLE);
schedule_timeout (HZ/10); schedule_timeout (HZ/10);
} }
up (&sem_exit); up (&sem_exit);
debug ("%s - Exit\n", __FUNCTION__); debug ("%s - Exit\n", __FUNCTION__);
} }
...@@ -1070,15 +1172,23 @@ void __exit ibmphp_hpc_stop_poll_thread (void) ...@@ -1070,15 +1172,23 @@ void __exit ibmphp_hpc_stop_poll_thread (void)
debug ("%s - Entry\n", __FUNCTION__); debug ("%s - Entry\n", __FUNCTION__);
ibmphp_shutdown = TRUE; ibmphp_shutdown = TRUE;
debug ("before locking operations \n");
ibmphp_lock_operations (); ibmphp_lock_operations ();
debug ("after locking operations \n");
// wait for poll thread to exit // wait for poll thread to exit
debug ("before sem_exit down \n");
down (&sem_exit); down (&sem_exit);
debug ("after sem_exit down \n");
// cleanup // cleanup
debug ("before free_hpc_access \n");
free_hpc_access (); free_hpc_access ();
debug ("after free_hpc_access \n");
ibmphp_unlock_operations (); ibmphp_unlock_operations ();
debug ("after unlock operations \n");
up (&sem_exit); up (&sem_exit);
debug ("after sem exit up\n");
debug ("%s - Exit\n", __FUNCTION__); debug ("%s - Exit\n", __FUNCTION__);
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -141,20 +141,5 @@ extern int pci_visit_dev (struct pci_visit *fn, ...@@ -141,20 +141,5 @@ extern int pci_visit_dev (struct pci_visit *fn,
struct pci_dev_wrapped *wrapped_dev, struct pci_dev_wrapped *wrapped_dev,
struct pci_bus_wrapped *wrapped_parent); 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 #endif
...@@ -6,10 +6,8 @@ export-objs := access.o hotplug.o pci-driver.o pci.o pool.o \ ...@@ -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 probe.o proc.o search.o compat.o
obj-y += access.o probe.o pci.o pool.o quirks.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_PM) += power.o
obj-$(CONFIG_HOTPLUG) += hotplug.o
obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_PROC_FS) += proc.o
ifndef CONFIG_SPARC64 ifndef CONFIG_SPARC64
......
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
#define TRUE (!FALSE) #define TRUE (!FALSE)
#endif #endif
static void #ifdef CONFIG_HOTPLUG
run_sbin_hotplug(struct pci_dev *pdev, int insert) static void run_sbin_hotplug(struct pci_dev *pdev, int insert)
{ {
int i; int i;
char *argv[3], *envp[8]; char *argv[3], *envp[8];
...@@ -45,13 +45,18 @@ run_sbin_hotplug(struct pci_dev *pdev, int insert) ...@@ -45,13 +45,18 @@ run_sbin_hotplug(struct pci_dev *pdev, int insert)
call_usermodehelper (argv [0], argv, envp); 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 * @dev: the device to insert
* @bus: where to insert it * @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 void
pci_insert_device(struct pci_dev *dev, struct pci_bus *bus) pci_insert_device(struct pci_dev *dev, struct pci_bus *bus)
...@@ -78,11 +83,11 @@ pci_free_resources(struct pci_dev *dev) ...@@ -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 * @dev: the device to remove
* *
* Delete the device structure from the device lists and * Delete the device structure from the device lists,
* notify userspace (/sbin/hotplug). * remove the /proc entry, and notify userspace (/sbin/hotplug).
*/ */
void void
pci_remove_device(struct pci_dev *dev) pci_remove_device(struct pci_dev *dev)
...@@ -94,10 +99,11 @@ pci_remove_device(struct pci_dev *dev) ...@@ -94,10 +99,11 @@ pci_remove_device(struct pci_dev *dev)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
pci_proc_detach_device(dev); pci_proc_detach_device(dev);
#endif #endif
/* notify userspace of hotplug device removal */ /* notify userspace of hotplug device removal */
run_sbin_hotplug(dev, FALSE); run_sbin_hotplug(dev, FALSE);
} }
#ifdef CONFIG_HOTPLUG
EXPORT_SYMBOL(pci_insert_device); EXPORT_SYMBOL(pci_insert_device);
EXPORT_SYMBOL(pci_remove_device); EXPORT_SYMBOL(pci_remove_device);
#endif
...@@ -479,10 +479,10 @@ struct pci_dev * __devinit pci_scan_slot(struct pci_dev *temp) ...@@ -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 * 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); pci_insert_device (dev, bus);
list_add_tail(&dev->bus_list, &bus->devices);
/* Fix up broken headers */ /* Fix up broken headers */
pci_fixup_device(PCI_FIXUP_HEADER, dev); pci_fixup_device(PCI_FIXUP_HEADER, dev);
...@@ -594,4 +594,5 @@ EXPORT_SYMBOL(pci_setup_device); ...@@ -594,4 +594,5 @@ EXPORT_SYMBOL(pci_setup_device);
EXPORT_SYMBOL(pci_add_new_bus); EXPORT_SYMBOL(pci_add_new_bus);
EXPORT_SYMBOL(pci_do_scan_bus); EXPORT_SYMBOL(pci_do_scan_bus);
EXPORT_SYMBOL(pci_scan_slot); EXPORT_SYMBOL(pci_scan_slot);
EXPORT_SYMBOL(pci_scan_bus);
#endif #endif
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#define PCI_CFG_SPACE_SIZE 256 #define PCI_CFG_SPACE_SIZE 256
static int proc_initialized; /* = 0 */
static loff_t static loff_t
proc_bus_pci_lseek(struct file *file, loff_t off, int whence) 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) ...@@ -410,6 +412,9 @@ int pci_proc_attach_device(struct pci_dev *dev)
struct proc_dir_entry *de, *e; struct proc_dir_entry *de, *e;
char name[16]; char name[16];
if (!proc_initialized)
return -EACCES;
if (!(de = bus->procdir)) { if (!(de = bus->procdir)) {
sprintf(name, "%02x", bus->number); sprintf(name, "%02x", bus->number);
de = bus->procdir = proc_mkdir(name, proc_bus_pci_dir); de = bus->procdir = proc_mkdir(name, proc_bus_pci_dir);
...@@ -446,6 +451,9 @@ int pci_proc_attach_bus(struct pci_bus* bus) ...@@ -446,6 +451,9 @@ int pci_proc_attach_bus(struct pci_bus* bus)
{ {
struct proc_dir_entry *de = bus->procdir; struct proc_dir_entry *de = bus->procdir;
if (!proc_initialized)
return -EACCES;
if (!de) { if (!de) {
char name[16]; char name[16];
sprintf(name, "%02x", bus->number); sprintf(name, "%02x", bus->number);
...@@ -595,6 +603,7 @@ static int __init pci_proc_init(void) ...@@ -595,6 +603,7 @@ static int __init pci_proc_init(void)
entry = create_proc_entry("devices", 0, proc_bus_pci_dir); entry = create_proc_entry("devices", 0, proc_bus_pci_dir);
if (entry) if (entry)
entry->proc_fops = &proc_bus_pci_dev_operations; entry->proc_fops = &proc_bus_pci_dev_operations;
proc_initialized = 1;
pci_for_each_dev(dev) { pci_for_each_dev(dev) {
pci_proc_attach_device(dev); pci_proc_attach_device(dev);
} }
......
...@@ -1020,6 +1020,16 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) ...@@ -1020,6 +1020,16 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
if (status) if (status)
return status; return status;
/* increment urb's reference count as part of giving it to the HCD
* (which now controls it). HCD guarantees that it either returns
* an error or calls giveback(), but not both.
*/
urb = usb_get_urb (urb);
if (urb->dev == hcd->self.root_hub) {
urb->transfer_flags |= URB_NO_DMA_MAP;
return rh_urb_enqueue (hcd, urb);
}
/* lower level hcd code should use *_dma exclusively */ /* lower level hcd code should use *_dma exclusively */
if (!(urb->transfer_flags & URB_NO_DMA_MAP)) { if (!(urb->transfer_flags & URB_NO_DMA_MAP)) {
if (usb_pipecontrol (urb->pipe)) if (usb_pipecontrol (urb->pipe))
...@@ -1038,16 +1048,7 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) ...@@ -1038,16 +1048,7 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
: PCI_DMA_TODEVICE); : PCI_DMA_TODEVICE);
} }
/* increment urb's reference count as part of giving it to the HCD return hcd->driver->urb_enqueue (hcd, urb, mem_flags);
* (which now controls it). HCD guarantees that it either returns
* an error or calls giveback(), but not both.
*/
urb = usb_get_urb (urb);
if (urb->dev == hcd->self.root_hub)
status = rh_urb_enqueue (hcd, urb);
else
status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
return status;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
/*****************************************************************************/ /*****************************************************************************/
#define __NO_VERSION__
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/fs.h> #include <linux/fs.h>
...@@ -561,35 +560,57 @@ static void put_mount (struct vfsmount **mount) ...@@ -561,35 +560,57 @@ static void put_mount (struct vfsmount **mount)
static int create_special_files (void) static int create_special_files (void)
{ {
struct dentry *parent; struct dentry *parent;
int retval; int retval = 0;
/* create the devices special file */ /* create the devices special file */
retval = get_mount (&usbdevice_fs_type, &usbdevfs_mount); retval = get_mount (&usbdevice_fs_type, &usbdevfs_mount);
if (retval) if (retval) {
return retval; err ("Unable to get usbdevfs mount");
goto exit;
}
retval = get_mount (&usb_fs_type, &usbfs_mount); retval = get_mount (&usb_fs_type, &usbfs_mount);
if (retval) { if (retval) {
put_mount (&usbfs_mount); err ("Unable to get usbfs mount");
return retval; goto error_clean_usbdevfs_mount;
} }
parent = usbfs_mount->mnt_sb->s_root; parent = usbfs_mount->mnt_sb->s_root;
devices_usbfs_dentry = fs_create_file ("devices", listmode | S_IFREG, parent, devices_usbfs_dentry = fs_create_file ("devices",
listmode | S_IFREG, parent,
NULL, &usbdevfs_devices_fops, NULL, &usbdevfs_devices_fops,
listuid, listgid); listuid, listgid);
if (devices_usbfs_dentry == NULL) { if (devices_usbfs_dentry == NULL) {
err ("Unable to create devices usbfs file"); err ("Unable to create devices usbfs file");
return -ENODEV; retval = -ENODEV;
goto error_clean_mounts;
} }
parent = usbdevfs_mount->mnt_sb->s_root; parent = usbdevfs_mount->mnt_sb->s_root;
devices_usbdevfs_dentry = fs_create_file ("devices", listmode | S_IFREG, parent, devices_usbdevfs_dentry = fs_create_file ("devices",
listmode | S_IFREG, parent,
NULL, &usbdevfs_devices_fops, NULL, &usbdevfs_devices_fops,
listuid, listgid); listuid, listgid);
if (devices_usbdevfs_dentry == NULL) { if (devices_usbdevfs_dentry == NULL) {
err ("Unable to create devices usbfs file"); err ("Unable to create devices usbfs file");
return -ENODEV; retval = -ENODEV;
goto error_remove_file;
} }
return 0; goto exit;
error_remove_file:
fs_remove_file (devices_usbfs_dentry);
devices_usbfs_dentry = NULL;
error_clean_mounts:
put_mount (&usbfs_mount);
error_clean_usbdevfs_mount:
put_mount (&usbdevfs_mount);
exit:
return retval;
} }
static void remove_special_files (void) static void remove_special_files (void)
......
...@@ -57,7 +57,7 @@ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) ...@@ -57,7 +57,7 @@ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label)
strcat(buf, tmp); strcat(buf, tmp);
} }
dbg ("%s: %s portroute %s", dbg ("%s: %s portroute %s",
ehci->hcd.self.bus_name, label, hcd_to_bus (&ehci->hcd)->bus_name, label,
buf); buf);
} }
} }
...@@ -122,7 +122,8 @@ dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) ...@@ -122,7 +122,8 @@ dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
} }
} }
static int dbg_status_buf (char *buf, unsigned len, char *label, u32 status) static int __attribute__((__unused__))
dbg_status_buf (char *buf, unsigned len, char *label, u32 status)
{ {
return snprintf (buf, len, return snprintf (buf, len,
"%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s", "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s",
...@@ -140,7 +141,8 @@ static int dbg_status_buf (char *buf, unsigned len, char *label, u32 status) ...@@ -140,7 +141,8 @@ static int dbg_status_buf (char *buf, unsigned len, char *label, u32 status)
); );
} }
static int dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable) static int __attribute__((__unused__))
dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable)
{ {
return snprintf (buf, len, return snprintf (buf, len,
"%s%sintrenable %02x%s%s%s%s%s%s", "%s%sintrenable %02x%s%s%s%s%s%s",
...@@ -213,19 +215,19 @@ dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) ...@@ -213,19 +215,19 @@ dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
static inline int __attribute__((__unused__)) static inline int __attribute__((__unused__))
dbg_status_buf (char *buf, unsigned len, char *label, u32 status) dbg_status_buf (char *buf, unsigned len, char *label, u32 status)
{} { return 0; }
static inline int __attribute__((__unused__)) static inline int __attribute__((__unused__))
dbg_command_buf (char *buf, unsigned len, char *label, u32 command) dbg_command_buf (char *buf, unsigned len, char *label, u32 command)
{} { return 0; }
static inline int __attribute__((__unused__)) static inline int __attribute__((__unused__))
dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable) dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable)
{} { return 0; }
static inline int __attribute__((__unused__)) static inline int __attribute__((__unused__))
dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status) dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status)
{} { return 0; }
#endif /* DEBUG */ #endif /* DEBUG */
...@@ -248,7 +250,16 @@ dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status) ...@@ -248,7 +250,16 @@ dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status)
dbg ("%s", _buf); \ dbg ("%s", _buf); \
} }
#ifdef DEBUG /*-------------------------------------------------------------------------*/
#ifdef STUB_DEBUG_FILES
static inline void create_debug_files (struct ehci_hcd *bus) { }
static inline void remove_debug_files (struct ehci_hcd *bus) { }
#else
/* troubleshooting help: expose state in driverfs */
#define speed_char(info1) ({ char tmp; \ #define speed_char(info1) ({ char tmp; \
switch (info1 & (3 << 12)) { \ switch (info1 & (3 << 12)) { \
...@@ -258,6 +269,49 @@ dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status) ...@@ -258,6 +269,49 @@ dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status)
default: tmp = '?'; break; \ default: tmp = '?'; break; \
}; tmp; }) }; tmp; })
static void qh_lines (struct ehci_qh *qh, char **nextp, unsigned *sizep)
{
u32 scratch;
struct list_head *entry;
struct ehci_qtd *td;
unsigned temp;
unsigned size = *sizep;
char *next = *nextp;
scratch = cpu_to_le32p (&qh->hw_info1);
temp = snprintf (next, size, "qh/%p dev%d %cs ep%d %08x %08x",
qh, scratch & 0x007f,
speed_char (scratch),
(scratch >> 8) & 0x000f,
scratch, cpu_to_le32p (&qh->hw_info2));
size -= temp;
next += temp;
list_for_each (entry, &qh->qtd_list) {
td = list_entry (entry, struct ehci_qtd,
qtd_list);
scratch = cpu_to_le32p (&td->hw_token);
temp = snprintf (next, size,
"\n\ttd/%p %s len=%d %08x urb %p",
td, ({ char *tmp;
switch ((scratch>>8)&0x03) {
case 0: tmp = "out"; break;
case 1: tmp = "in"; break;
case 2: tmp = "setup"; break;
default: tmp = "?"; break;
} tmp;}),
(scratch >> 16) & 0x7fff,
scratch,
td->urb);
size -= temp;
next += temp;
}
temp = snprintf (next, size, "\n");
*sizep = size - temp;
*nextp = next + temp;
}
static ssize_t static ssize_t
show_async (struct device *dev, char *buf, size_t count, loff_t off) show_async (struct device *dev, char *buf, size_t count, loff_t off)
{ {
...@@ -284,49 +338,21 @@ show_async (struct device *dev, char *buf, size_t count, loff_t off) ...@@ -284,49 +338,21 @@ show_async (struct device *dev, char *buf, size_t count, loff_t off)
if (ehci->async) { if (ehci->async) {
qh = ehci->async; qh = ehci->async;
do { do {
u32 scratch; qh_lines (qh, &next, &size);
struct list_head *entry; } while ((qh = qh->qh_next.qh) != ehci->async);
struct ehci_qtd *td;
scratch = cpu_to_le32p (&qh->hw_info1);
temp = snprintf (next, size, "qh %p dev%d %cs ep%d",
qh, scratch & 0x007f,
speed_char (scratch),
(scratch >> 8) & 0x000f);
size -= temp;
next += temp;
list_for_each (entry, &qh->qtd_list) {
td = list_entry (entry, struct ehci_qtd,
qtd_list);
scratch = cpu_to_le32p (&td->hw_token);
temp = snprintf (next, size,
", td %p len=%d tok %04x %s",
td, scratch >> 16,
scratch & 0xffff,
({ char *tmp;
switch ((scratch>>8)&0x03) {
case 0: tmp = "out"; break;
case 1: tmp = "in"; break;
case 2: tmp = "setup"; break;
default: tmp = "?"; break;
} tmp;})
);
size -= temp;
next += temp;
} }
if (ehci->reclaim) {
temp = snprintf (next, size, "\n"); temp = snprintf (next, size, "\nreclaim =\n");
size -= temp; size -= temp;
next += temp; next += temp;
} while ((qh = qh->qh_next.qh) != ehci->async); qh_lines (ehci->reclaim, &next, &size);
} }
spin_unlock_irqrestore (&ehci->lock, flags); spin_unlock_irqrestore (&ehci->lock, flags);
return count - size; return count - size;
} }
static DEVICE_ATTR (async, S_IRUSR, show_async, NULL); static DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
#define DBG_SCHED_LIMIT 64 #define DBG_SCHED_LIMIT 64
...@@ -373,7 +399,7 @@ show_periodic (struct device *dev, char *buf, size_t count, loff_t off) ...@@ -373,7 +399,7 @@ show_periodic (struct device *dev, char *buf, size_t count, loff_t off)
do { do {
switch (tag) { switch (tag) {
case Q_TYPE_QH: case Q_TYPE_QH:
temp = snprintf (next, size, " intr-%d %p", temp = snprintf (next, size, " qh%d/%p",
p.qh->period, p.qh); p.qh->period, p.qh);
size -= temp; size -= temp;
next += temp; next += temp;
...@@ -387,12 +413,14 @@ show_periodic (struct device *dev, char *buf, size_t count, loff_t off) ...@@ -387,12 +413,14 @@ show_periodic (struct device *dev, char *buf, size_t count, loff_t off)
&p.qh->hw_info1); &p.qh->hw_info1);
temp = snprintf (next, size, temp = snprintf (next, size,
" (%cs dev%d ep%d)", " (%cs dev%d ep%d [%d/%d] %d)",
speed_char (scratch), speed_char (scratch),
scratch & 0x007f, scratch & 0x007f,
(scratch >> 8) & 0x000f); (scratch >> 8) & 0x000f,
p.qh->usecs, p.qh->c_usecs,
scratch >> 16);
/* FIXME TDs too */ /* FIXME TD info too */
if (seen_count < DBG_SCHED_LIMIT) if (seen_count < DBG_SCHED_LIMIT)
seen [seen_count++].qh = p.qh; seen [seen_count++].qh = p.qh;
...@@ -434,7 +462,7 @@ show_periodic (struct device *dev, char *buf, size_t count, loff_t off) ...@@ -434,7 +462,7 @@ show_periodic (struct device *dev, char *buf, size_t count, loff_t off)
return count - size; return count - size;
} }
static DEVICE_ATTR (periodic, S_IRUSR, show_periodic, NULL); static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
#undef DBG_SCHED_LIMIT #undef DBG_SCHED_LIMIT
...@@ -522,7 +550,7 @@ show_registers (struct device *dev, char *buf, size_t count, loff_t off) ...@@ -522,7 +550,7 @@ show_registers (struct device *dev, char *buf, size_t count, loff_t off)
return count - size; return count - size;
} }
static DEVICE_ATTR (registers, S_IRUSR, show_registers, NULL); static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
static inline void create_debug_files (struct ehci_hcd *bus) static inline void create_debug_files (struct ehci_hcd *bus)
{ {
...@@ -538,14 +566,5 @@ static inline void remove_debug_files (struct ehci_hcd *bus) ...@@ -538,14 +566,5 @@ static inline void remove_debug_files (struct ehci_hcd *bus)
device_remove_file (&bus->hcd.pdev->dev, &dev_attr_registers); device_remove_file (&bus->hcd.pdev->dev, &dev_attr_registers);
} }
#else /* DEBUG */ #endif /* STUB_DEBUG_FILES */
static inline void create_debug_files (struct ehci_hcd *bus)
{
}
static inline void remove_debug_files (struct ehci_hcd *bus)
{
}
#endif /* DEBUG */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -774,7 +774,7 @@ ioctl_scanner(struct inode *inode, struct file *file, ...@@ -774,7 +774,7 @@ ioctl_scanner(struct inode *inode, struct file *file,
if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg))) if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg)))
return -EFAULT; return -EFAULT;
nb = le16_to_cpup(&cmsg.req.wLength); nb = cmsg.req.wLength;
if (nb > sizeof(buf)) if (nb > sizeof(buf))
return -EINVAL; return -EINVAL;
...@@ -789,8 +789,8 @@ ioctl_scanner(struct inode *inode, struct file *file, ...@@ -789,8 +789,8 @@ ioctl_scanner(struct inode *inode, struct file *file,
ret = usb_control_msg(dev, pipe, cmsg.req.bRequest, ret = usb_control_msg(dev, pipe, cmsg.req.bRequest,
cmsg.req.bRequestType, cmsg.req.bRequestType,
le16_to_cpup(&cmsg.req.wValue), cmsg.req.wValue,
le16_to_cpup(&cmsg.req.wIndex), cmsg.req.wIndex,
buf, nb, HZ); buf, nb, HZ);
if (ret < 0) { if (ret < 0) {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment