mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
[IA64] Multiple outstanding ptc.g instruction support
According to SDM2.2, Itanium supports multiple outstanding ptc.g instructions. But current kernel function ia64_global_tlb_purge() uses a spinlock to serialize ptc.g instructions issued by multiple processors. This serialization might have scalability issue on a big SMP machine where many processors could purge TLB in parallel. The patch fixes this problem by issuing multiple ptc.g instructions in ia64_global_tlb_purge(). It also adds support for the "PALO" table to get a platform view of the max number of outstanding ptc.g instructions (which may be different from the processor view found from PAL_VM_SUMMARY). PALO specification can be found at: http://www.dig64.org/home/DIG64_PALO_R1_0.pdf spinaphore implementation by Matthew Wilcox. Signed-off-by: Fenghua Yu <fenghua.yu@intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/mca.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
#define EFI_DEBUG 0
|
||||
|
||||
@@ -403,6 +404,41 @@ efi_get_pal_addr (void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static u8 __init palo_checksum(u8 *buffer, u32 length)
|
||||
{
|
||||
u8 sum = 0;
|
||||
u8 *end = buffer + length;
|
||||
|
||||
while (buffer < end)
|
||||
sum = (u8) (sum + *(buffer++));
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse and handle PALO table which is published at:
|
||||
* http://www.dig64.org/home/DIG64_PALO_R1_0.pdf
|
||||
*/
|
||||
static void __init handle_palo(unsigned long palo_phys)
|
||||
{
|
||||
struct palo_table *palo = __va(palo_phys);
|
||||
u8 checksum;
|
||||
|
||||
if (strncmp(palo->signature, PALO_SIG, sizeof(PALO_SIG) - 1)) {
|
||||
printk(KERN_INFO "PALO signature incorrect.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
checksum = palo_checksum((u8 *)palo, palo->length);
|
||||
if (checksum) {
|
||||
printk(KERN_INFO "PALO checksum incorrect.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
setup_ptcg_sem(palo->max_tlb_purges, 1);
|
||||
}
|
||||
|
||||
void
|
||||
efi_map_pal_code (void)
|
||||
{
|
||||
@@ -432,6 +468,7 @@ efi_init (void)
|
||||
u64 efi_desc_size;
|
||||
char *cp, vendor[100] = "unknown";
|
||||
int i;
|
||||
unsigned long palo_phys;
|
||||
|
||||
/*
|
||||
* It's too early to be able to use the standard kernel command line
|
||||
@@ -496,6 +533,8 @@ efi_init (void)
|
||||
efi.hcdp = EFI_INVALID_TABLE_ADDR;
|
||||
efi.uga = EFI_INVALID_TABLE_ADDR;
|
||||
|
||||
palo_phys = EFI_INVALID_TABLE_ADDR;
|
||||
|
||||
for (i = 0; i < (int) efi.systab->nr_tables; i++) {
|
||||
if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
|
||||
efi.mps = config_tables[i].table;
|
||||
@@ -515,10 +554,17 @@ efi_init (void)
|
||||
} else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
|
||||
efi.hcdp = config_tables[i].table;
|
||||
printk(" HCDP=0x%lx", config_tables[i].table);
|
||||
} else if (efi_guidcmp(config_tables[i].guid,
|
||||
PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID) == 0) {
|
||||
palo_phys = config_tables[i].table;
|
||||
printk(" PALO=0x%lx", config_tables[i].table);
|
||||
}
|
||||
}
|
||||
printk("\n");
|
||||
|
||||
if (palo_phys != EFI_INVALID_TABLE_ADDR)
|
||||
handle_palo(palo_phys);
|
||||
|
||||
runtime = __va(efi.systab->runtime);
|
||||
efi.get_time = phys_get_time;
|
||||
efi.set_time = phys_set_time;
|
||||
|
Reference in New Issue
Block a user