Minor SMP fixes. Fix to linuxpci to catch buggy chipsets
This commit is contained in:
parent
350fa4e519
commit
ce6c4c7195
7 changed files with 70 additions and 19 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
#include <smp/atomic.h>
|
||||
int this_processors_id(void);
|
||||
void stop_cpu(int processor_id);
|
||||
void start_cpu(int processor_id);
|
||||
void startup_other_cpus(void);
|
||||
int start_cpu(int processor_id);
|
||||
void startup_other_cpus(unsigned long *processor_map);
|
||||
#else
|
||||
#define this_processors_id() 0
|
||||
#define startup_other_cpus() do {} while(0)
|
||||
|
|
|
|||
|
|
@ -129,8 +129,26 @@ void pci_get_size(struct pci_dev *dev, unsigned long reg, unsigned long addr)
|
|||
// restore addr
|
||||
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), addr);
|
||||
|
||||
// some broken hardware has read-only registers that do not
|
||||
// really size correctly. You can tell this if addr == size
|
||||
// Example: the acer m7229 has BARs 1-4 normally read-only.
|
||||
// so BAR1 at offset 0x10 reads 0x1f1. If you size that register
|
||||
// by writing 0xffffffff to it, it will read back as 0x1f1 -- a
|
||||
// violation of the spec.
|
||||
// We catch this case and ignore it by settting size and type to 0.
|
||||
// This incidentally catches the common case where registers
|
||||
// read back as 0 for both address and size.
|
||||
if (addr == size) {
|
||||
printk_err(__FUNCTION__
|
||||
"dev_fn 0x%x, register %d, read-only"
|
||||
" SO, ignoring it\n",
|
||||
dev->devfn, reg);
|
||||
printk_err("addr was 0x%x, size was 0x%x\n",addr,size);
|
||||
type = 0;
|
||||
size = 0;
|
||||
}
|
||||
// Now compute the actual size, See PCI Spec 6.2.5.1 ...
|
||||
if (size & PCI_BASE_ADDRESS_SPACE_IO) {
|
||||
else if (size & PCI_BASE_ADDRESS_SPACE_IO) {
|
||||
type = size & (~PCI_BASE_ADDRESS_IO_MASK);
|
||||
size &= (PCI_BASE_ADDRESS_IO_MASK);
|
||||
// BUG! Top 16 bits can be zero (or not)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#include <string.h>
|
||||
#include <printk.h>
|
||||
|
||||
void smp_write_config_table(void *v)
|
||||
void smp_write_config_table(void *v, unsigned long * processor_map)
|
||||
{
|
||||
int ioapicid = 0;
|
||||
static const char sig[4] = "PCMP";
|
||||
|
|
@ -28,7 +28,7 @@ void smp_write_config_table(void *v)
|
|||
mc->reserved = 0;
|
||||
|
||||
|
||||
smp_write_processors(mc);
|
||||
smp_write_processors(mc, processor_map);
|
||||
ioapicid = 2;
|
||||
|
||||
smp_write_bus(mc, 0, "PCI ");
|
||||
|
|
@ -122,10 +122,10 @@ void smp_write_config_table(void *v)
|
|||
mc, smp_next_mpe_entry(mc));
|
||||
}
|
||||
|
||||
void write_smp_table(void *v)
|
||||
void write_smp_table(void *v, unsigned long *processor_map)
|
||||
{
|
||||
smp_write_floating_table(v);
|
||||
smp_write_config_table(v);
|
||||
smp_write_config_table(v, processor_map);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue