Minor SMP fixes. Fix to linuxpci to catch buggy chipsets

This commit is contained in:
Ronald G. Minnich 2001-10-15 18:19:40 +00:00
commit ce6c4c7195
7 changed files with 70 additions and 19 deletions

View file

@ -238,7 +238,8 @@ void smp_write_processor(struct mp_config_table *mc,
unsigned char apicid, unsigned char apicver,
unsigned char cpuflag, unsigned int cpufeature,
unsigned int featureflag);
void smp_write_processors(struct mp_config_table *mc);
void smp_write_processors(struct mp_config_table *mc,
unsigned long *processor_map);
void smp_write_bus(struct mp_config_table *mc,
unsigned char id, unsigned char *bustype);
void smp_write_ioapic(struct mp_config_table *mc,
@ -264,7 +265,7 @@ void smp_write_compatibility_address_space(struct mp_config_table *mc,
unsigned int range_list);
unsigned char smp_compute_checksum(void *v, int len);
void smp_write_floating_table(void *v);
void write_smp_table(void *v);
void write_smp_table(void *v, unsigned long *processor_map);
#else /* HAVE_MP_TABLE */

View file

@ -109,10 +109,12 @@ void secondary_cpu_init(void)
unsigned long totalram;
int processor_id;
printk_spew(__FUNCTION__ "\n");
atomic_inc(&active_cpus);
totalram = get_ramsize();
processor_id = cpu_initialize(totalram);
atomic_dec(&active_cpus);
printk_spew(__FUNCTION__ " id is %d\n", processor_id);
stop_cpu(processor_id);
}
@ -135,6 +137,18 @@ static void wait_for_other_cpus(void)
void hardwaremain(int boot_complete)
{
// The processor map.
// Now that SMP is in linuxbios, and Linux counts on us
// giving accurate information about processors, we need a map
// of what processors are out there. This could be a bit mask,
// but we will be optimistic and hope we someday run on
// REALLY BIG SMPs. Also we may need more than one bit of
// info per processor at some point. I hope we don't need
// anything more complex than an int.
unsigned long processor_map[MAX_CPUS];
// Processor ID of the BOOT cpu (i.e. the one running this code
int boot_cpu;
// Comment: the NEW_SUPERIO architecture is actually pretty good.
// I think we need to move to the same sort of architecture for
// everything: A config file generated sequence of calls
@ -189,12 +203,14 @@ void hardwaremain(int boot_complete)
printk_info("totalram: %ldM\n", totalram/1024);
/* Fully initialize the cpu before configuring the bus */
cpu_initialize(totalram);
boot_cpu = cpu_initialize(totalram);
printk_spew("BOOT CPU is %d\n", boot_cpu);
processor_map[boot_cpu] = CPU_BOOTPROCESSOR|CPU_ENABLED;
/* Now start the other cpus initializing
* The sooner they start the sooner they stop.
*/
startup_other_cpus();
startup_other_cpus(processor_map);
// Now do the real bus
// we round the total ram up a lot for thing like the SISFB, which
@ -233,7 +249,7 @@ void hardwaremain(int boot_complete)
pci_zero_irq_settings();
/* copy the smp block to address 0 */
write_smp_table((void *)16);
write_smp_table((void *)16, processor_map);
post_code(0x96);
check_pirq_routing_table();

View file

@ -90,7 +90,8 @@ void smp_write_processor(struct mp_config_table *mc,
* Having the proper apicid's in the table so the non-bootstrap
* processors can be woken up should be enough.
*/
void smp_write_processors(struct mp_config_table *mc)
void smp_write_processors(struct mp_config_table *mc,
unsigned long *processor_map)
{
int i;
int processor_id;
@ -105,7 +106,7 @@ void smp_write_processors(struct mp_config_table *mc)
cpu_feature_flags = edx;
for(i = 0; i < MAX_CPUS; i++) {
smp_write_processor(mc, i, apic_version,
((processor_id == i)? CPU_BOOTPROCESSOR:0) | CPU_ENABLED,
processor_map[i],
cpu_features, cpu_feature_flags
);

View file

@ -1,4 +1,5 @@
#include <smp/start_stop.h>
#include <arch/smp/mpspec.h>
#include <cpu/p6/apic.h>
#include <delay.h>
@ -57,7 +58,10 @@ void stop_cpu(int apicid)
}
void start_cpu(int apicid)
// This is a lot more paranoid now, since Linux can NOT handle
// being told there is a CPU when none exists. So any errors
// will return 0, meaning no CPU.
int start_cpu(int apicid)
{
int timeout;
unsigned long send_status, accept_status, start_eip;
@ -87,7 +91,10 @@ void start_cpu(int apicid)
send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
} while (send_status && (timeout++ < 1000));
if (timeout >= 1000) {
printk_spew("timed out\n");
printk_err("CPU %d: First apic write timed out. Disabling\n",
apicid);
// too bad.
return 0;
}
mdelay(10);
@ -108,7 +115,10 @@ void start_cpu(int apicid)
send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
} while (send_status && (timeout++ < 1000));
if (timeout >= 1000) {
printk_spew("timed out\n");
printk_err("CPU %d: Second apic write timed out. Disabling\n",
apicid);
// too bad.
return 0;
}
/* FIXME start_eip should be more flexible! */
@ -178,9 +188,12 @@ void start_cpu(int apicid)
printk_warning("APIC never delivered???\n");
if (accept_status)
printk_warning("APIC delivery error (%lx).\n", accept_status);
if (send_status || accept_status)
return 0;
return 1;
}
void startup_other_cpus(void)
void startup_other_cpus(unsigned long *processor_map)
{
int apicid = this_processors_id();
int i;
@ -189,6 +202,8 @@ void startup_other_cpus(void)
if (i == apicid ) {
continue;
}
start_cpu(i);
if (start_cpu(i))
processor_map[i] = CPU_ENABLED;
}
}