All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ingo Molnar <mingo@elte.hu>
To: Len Brown <lenb@kernel.org>, "H. Peter Anvin" <hpa@zytor.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Yinghai Lu <yinghai@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Linus Torvalds <torvalds@linux-foundation.org>
Cc: sfi-devel@simplefirmware.org, linux-kernel@vger.kernel.org,
	Feng Tang <feng.tang@intel.com>, Len Brown <len.brown@intel.com>
Subject: Re: [PATCH 3/8] SFI: core support
Date: Tue, 23 Jun 2009 09:56:43 +0200	[thread overview]
Message-ID: <20090623075643.GC6397@elte.hu> (raw)
In-Reply-To: <8d9bab79ce1169afd419035f70177e52d47626ca.1245740912.git.len.brown@intel.com>


> --- /dev/null
> +++ b/arch/x86/kernel/sfi.c

> +#include <linux/init.h>
> +#include <linux/efi.h>
> +#include <linux/cpumask.h>
> +#include <linux/module.h>
> +#include <linux/irq.h>
> +#include <linux/bootmem.h>
> +#include <linux/io.h>
> +#include <linux/acpi.h>
> +#include <linux/efi.h>
> +#include <linux/sfi.h>
> +
> +#include <asm/pgtable.h>
> +#include <asm/io_apic.h>
> +#include <asm/apic.h>
> +#include <asm/mpspec.h>
> +
> +#include <asm/e820.h>
> +#include <asm/setup.h>

Please try to use the include files style in arch/x86/mm/fault.c. It 
is minimalistic and deterministically ordered as well, so it will 
look in a pleasant way long-term too .

> +#undef PREFIX

Why undefine it? No header should set 'PREFIX' - if it does it needs 
fixing.

> +#define PREFIX "SFI: "
>
> +#ifdef CONFIG_X86_LOCAL_APIC
> +static u64 sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
> +#endif

if SFI adds a 'depends on X86_LOCAL_APIC' the ugly #ifdef can be 
dropped.

> +
> +extern int __init sfi_parse_xsdt(struct sfi_table_header *table);
> +static int __init sfi_parse_cpus(struct sfi_table_header *table);
> +static int __init sfi_parse_apic(struct sfi_table_header *table);

These should be in a header i guess.

> +
> +void __init __iomem *
> +arch_early_ioremap(unsigned long phys, unsigned long size)
> +{
> +	return early_ioremap(phys, size);
> +}
> +
> +void __init arch_early_iounmap(void __iomem *virt, unsigned long size)
> +{
> +	early_iounmap(virt, size);
> +}

Should be in a separate series and not added to sfi.c but to core 
x86.

> +
> +static ulong __init sfi_early_find_syst(void)

Please use C types such as 'unsigned long'.

> +{
> +	unsigned long i;

... like here.

> +	char *pchar = (char *)SFI_SYST_SEARCH_BEGIN;
> +
> +	for (i = 0; SFI_SYST_SEARCH_BEGIN + i < SFI_SYST_SEARCH_END; i += 16, pchar += 16) {

What does the magic constant '16' mean here?

> +		if (!strncmp(SFI_SIG_SYST, pchar, SFI_SIGNATURE_SIZE))
> +			return SFI_SYST_SEARCH_BEGIN + i;
> +	}
> +	return 0;
> +}
> +
> +/*
> + * called in a early boot phase before the paging table is created,
> + * setup a mmap table in e820 format
> + */
> +int __init sfi_init_memory_map(void)
> +{
> +	struct sfi_table_simple *syst, *mmapt;
> +	struct sfi_mem_entry *mentry;
> +	unsigned long long start, end, size;
> +	int i, num, type, tbl_cnt;
> +	u64 *pentry;
> +
> +	if (sfi_disabled)
> +		return -1;
> +
> +	/* first search the syst table */
> +	syst = (struct sfi_table_simple *)sfi_early_find_syst();

why doesnt sfi_early_find_syst() return the proper type?

> +	if (!syst)
> +		return -1;
> +
> +	tbl_cnt = (syst->header.length - sizeof(struct sfi_table_header)) / sizeof(u64);
> +	pentry = syst->pentry;
> +
> +	/* walk through the syst to search the mmap table */
> +	mmapt = NULL;
> +	for (i = 0; i < tbl_cnt; i++) {
> +		if (!strncmp(SFI_SIG_MMAP, (char *)(u32)*pentry, 4)) {
> +			mmapt = (struct sfi_table_simple *)(u32)*pentry;
> +			break;
> +		}
> +		pentry++;
> +	}
> +	if (!mmapt)
> +		return -1;
> +
> +	/* refer copy_e820_memory() */
> +	num = SFI_GET_ENTRY_NUM(mmapt, sfi_mem_entry);
> +	mentry = (struct sfi_mem_entry *)mmapt->pentry;
> +	for (i = 0; i < num; i++) {
> +		start = mentry->phy_start;
> +		size = mentry->pages << PAGE_SHIFT;
> +		end = start + size;
> +
> +		if (start > end)
> +			return -1;
> +
> +		pr_debug(PREFIX "start = 0x%08x end = 0x%08x type = %d\n",
> +			(u32)start, (u32)end, mentry->type);
> +
> +		/* translate SFI mmap type to E820 map type */
> +		switch (mentry->type) {
> +		case EFI_CONVENTIONAL_MEMORY:
> +			type = E820_RAM;
> +			break;
> +		case EFI_MEMORY_MAPPED_IO:
> +		case EFI_UNUSABLE_MEMORY:
> +		case EFI_RUNTIME_SERVICES_DATA:
> +			mentry++;
> +			continue;
> +		default:
> +			type = E820_RESERVED;
> +		}
> +
> +		e820_add_region(start, size, type);
> +		mentry++;
> +	}
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_X86_LOCAL_APIC
> +void __init mp_sfi_register_lapic_address(u64 address)
> +{
> +	mp_lapic_addr = (unsigned long) address;

mp_lapic_addr should have the proper type i guess.

> +
> +	set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
> +
> +	if (boot_cpu_physical_apicid == -1U)
> +		boot_cpu_physical_apicid = read_apic_id();
> +
> +	pr_info(PREFIX "Boot CPU = %d\n", boot_cpu_physical_apicid);

Should be pr_debug() i guess - we know the boot CPU from a number of 
other places already.

> +}
> +
> +/* All CPUs enumerated by SFI must be present and enabled */
> +void __cpuinit mp_sfi_register_lapic(u8 id)
> +{
> +	struct mpc_cpu cpu;
> +	int boot_cpu = 0;
> +
> +	if (MAX_APICS - id <= 0) {
> +		printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
> +			id, MAX_APICS);
> +		return;
> +	}
> +
> +	if (id == boot_cpu_physical_apicid)
> +		boot_cpu = 1;
> +
> +	cpu.type = MP_PROCESSOR;
> +	cpu.apicid = id;
> +	cpu.apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
> +	cpu.cpuflag = CPU_ENABLED;
> +	cpu.cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
> +	cpu.cpufeature = (boot_cpu_data.x86 << 8) |
> +		(boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
> +	cpu.featureflag = boot_cpu_data.x86_capability[0];
> +	cpu.reserved[0] = 0;
> +	cpu.reserved[1] = 0;

Nice trick - MP-spec is still useful after all.

> +
> +	generic_processor_info(id, cpu.apicver);
> +}
> +
> +static int __init sfi_parse_cpus(struct sfi_table_header *table)
> +{
> +	struct sfi_table_simple *sb;
> +	struct sfi_cpu_table_entry *pentry;
> +	int i;
> +	int cpu_num;
> +
> +	BUG_ON(!table);

Can this happen? If yes, is a boot crash the best answer?

> +	sb = (struct sfi_table_simple *)table;
> +
> +	cpu_num = SFI_GET_ENTRY_NUM(sb, sfi_cpu_table_entry);
> +	pentry = (struct sfi_cpu_table_entry *) sb->pentry;

(unneeded space character)

> +
> +	for (i = 0; i < cpu_num; i++) {
> +		mp_sfi_register_lapic(pentry->apicid);
> +		pentry++;
> +	}
> +
> +	smp_found_config = 1;
> +	return 0;
> +}
> +#endif /* CONFIG_X86_LOCAL_APIC */
> +
> +#ifdef	CONFIG_X86_IO_APIC

Should SFI add 'depends on X86_IO_APIC' perhaps? (or do you 
anticipate IO-APIC-less implementations?)


> +static struct mp_ioapic_routing {
> +	int			apic_id;
> +	int			gsi_base;
> +	int			gsi_end;
> +	u32			pin_programmed[4];
> +} mp_ioapic_routing[MAX_IO_APICS];

Data structures should be defined at the top of the .c file, not 
hidden in the middle.

> +
> +/* refer acpi/boot.c */
> +static u8 __init uniq_ioapic_id(u8 id)
> +{
> +#ifdef CONFIG_X86_32
> +	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
> +	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
> +		return io_apic_get_unique_id(nr_ioapics, id);
> +	else
> +		return id;
> +#else
> +	int i;
> +	DECLARE_BITMAP(used, 256);
> +	bitmap_zero(used, 256);

Newline needed after local variabe definition blocks.

> +	for (i = 0; i < nr_ioapics; i++) {
> +		struct mpc_ioapic *ia = &mp_ioapics[i];
> +		__set_bit(ia->apicid, used);
> +	}
> +	if (!test_bit(id, used))
> +		return id;
> +	return find_first_zero_bit(used, 256);
> +#endif
> +}

Why is the 32-bit and 64-bit version so different? Please unify 
first before adding new functionality.

> +
> +
> +void __init mp_sfi_register_ioapic(u8 id, u32 paddr)
> +{
> +	int idx = 0;
> +	int tmpid;
> +	static u32 gsi_base;
> +
> +	if (nr_ioapics >= MAX_IO_APICS) {
> +		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
> +			"(found %d)\n", MAX_IO_APICS, nr_ioapics);
> +		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
> +	}
> +	if (!paddr) {
> +		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
> +			" found in MADT table, skipping!\n");
> +		return;
> +	}
> +
> +	idx = nr_ioapics;
> +
> +	mp_ioapics[idx].type = MP_IOAPIC;
> +	mp_ioapics[idx].flags = MPC_APIC_USABLE;
> +	mp_ioapics[idx].apicaddr = paddr;
> +
> +	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, paddr);
> +	tmpid = uniq_ioapic_id(id);
> +	if (tmpid == -1)
> +		return;
> +
> +	mp_ioapics[idx].apicid = tmpid;
> +#ifdef CONFIG_X86_32
> +	mp_ioapics[idx].apicver = io_apic_get_version(idx);
> +#else
> +	mp_ioapics[idx].apicver = 0;
> +#endif

Could this #ifdef be eliminated?

> +
> +	pr_info(PREFIX "IOAPIC[%d]: apic_id %d, version %d, address 0x%x\n",
> +		idx, mp_ioapics[idx].apicid,
> +		mp_ioapics[idx].apicver, (u32)mp_ioapics[idx].apicaddr);
> +	/*
> +	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
> +	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
> +	 */
> +	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].apicid;
> +	mp_ioapic_routing[idx].gsi_base = gsi_base;
> +	mp_ioapic_routing[idx].gsi_end = gsi_base +
> +		io_apic_get_redir_entries(idx);
> +	gsi_base = mp_ioapic_routing[idx].gsi_end + 1;
> +	pr_info(PREFIX "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
> +	       "GSI %d-%d\n", idx, mp_ioapics[idx].apicid,
> +	       mp_ioapics[idx].apicver, (u32)mp_ioapics[idx].apicaddr,
> +	       mp_ioapic_routing[idx].gsi_base,
> +	       mp_ioapic_routing[idx].gsi_end);
> +
> +	nr_ioapics++;
> +}
> +
> +static int __init sfi_parse_apic(struct sfi_table_header *table)
> +{
> +	struct sfi_table_simple *sb;
> +	struct sfi_apic_table_entry *pentry;
> +	int i, num;
> +
> +	BUG_ON(!table);

Same as comment above - is this case anticipated? If yes, is a crash 
the best answer?

> +	sb = (struct sfi_table_simple *)table;
> +
> +	num = SFI_GET_ENTRY_NUM(sb, sfi_apic_table_entry);
> +	pentry = (struct sfi_apic_table_entry *) sb->pentry;
> +	for (i = 0; i < num; i++) {
> +		mp_sfi_register_ioapic(i, pentry->phy_addr);
> +		pentry++;
> +	}
> +
> +	WARN_ON(pic_mode);
> +	pic_mode = 0;

If this warning can occor, please use WARN() instead with a 
user-parseable message.

> +	return 0;
> +}
> +#endif /* CONFIG_X86_IO_APIC */
> +
> +/*
> + * sfi_platform_init(): register lapics & io-apics
> + */
> +int __init sfi_platform_init(void)
> +{
> +#ifdef CONFIG_X86_LOCAL_APIC
> +	mp_sfi_register_lapic_address(sfi_lapic_addr);
> +	sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, 0, sfi_parse_cpus);
> +#endif
> +#ifdef CONFIG_X86_IO_APIC
> +	sfi_table_parse(SFI_SIG_APIC, NULL, NULL, 0, sfi_parse_apic);
> +#endif

Both of these #ifdefs would go away with the 'depends on' 
suggestions i made above.

Also, sfi_parse_apic() should be named sfr_parse_ioapic() ?

> +	return 0;
> +}
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 1266ead..c3e39b5 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -11,6 +11,7 @@ obj-$(CONFIG_PARISC)		+= parisc/
>  obj-$(CONFIG_RAPIDIO)		+= rapidio/
>  obj-y				+= video/
>  obj-$(CONFIG_ACPI)		+= acpi/
> +obj-$(CONFIG_SFI)		+= sfi/
>  # PnP must come after ACPI since it will eventually need to check if acpi
>  # was used and do nothing if so
>  obj-$(CONFIG_PNP)		+= pnp/
> diff --git a/drivers/sfi/Makefile b/drivers/sfi/Makefile
> new file mode 100644
> index 0000000..f176470
> --- /dev/null
> +++ b/drivers/sfi/Makefile
> @@ -0,0 +1 @@
> +obj-y	+= sfi_core.o
> diff --git a/drivers/sfi/sfi_core.c b/drivers/sfi/sfi_core.c
> new file mode 100644
> index 0000000..0a9b72d
> --- /dev/null
> +++ b/drivers/sfi/sfi_core.c
> @@ -0,0 +1,403 @@
> +/* sfi_core.c Simple Firmware Interface - core internals */
> +
> +/*
> + * Copyright (C) 2009, Intel Corp.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions, and the following disclaimer,
> + *    without modification.
> + * 2. Redistributions in binary form must reproduce at minimum a disclaimer
> + *    substantially similar to the "NO WARRANTY" disclaimer below
> + *    ("Disclaimer") and any redistribution must be conditioned upon
> + *    including a substantially similar Disclaimer requirement for further
> + *    binary redistribution.
> + * 3. Neither the names of the above-listed copyright holders nor the names
> + *    of any contributors may be used to endorse or promote products derived
> + *    from this software without specific prior written permission.
> + *
> + * Alternatively, this software may be distributed under the terms of the
> + * GNU General Public License ("GPL") version 2 as published by the Free
> + * Software Foundation.
> + *
> + * NO WARRANTY
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
> + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
> + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGES.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/smp.h>
> +#include <linux/string.h>
> +#include <linux/types.h>
> +#include <linux/irq.h>
> +#include <linux/errno.h>
> +#include <linux/sfi.h>
> +#include <linux/bootmem.h>
> +#include <linux/module.h>
> +#include <asm/pgtable.h>
> +#include "sfi_core.h"
> +
> +#undef PREFIX
> +#define PREFIX	"SFI: "
> +
> +int sfi_disabled;

Should be __read_mostly? (other read-mostly variables below too i 
guess)

> +EXPORT_SYMBOL(sfi_disabled);
> +
> +#define SFI_MAX_TABLES		64

Kernels we release will live 5-10 years easily - new hw is never 
expected to have more than 64 tables?

> +struct sfi_internal_syst sfi_tblist;
> +static struct sfi_table_desc sfi_initial_tables[SFI_MAX_TABLES] __initdata;
> +
> +/*
> + * flag for whether using ioremap() to map the sfi tables, if yes
> + * each table only need be mapped once, otherwise each arch's
> + * early_ioremap  and early_iounmap should be used each time a
> + * table is visited
> + */
> +static u32 sfi_tbl_permanant_mapped;
> +
> +static void __iomem *sfi_map_memory(u32 phys, u32 size)
> +{
> +	if (!phys || !size)
> +		return NULL;
> +
> +	if (sfi_tbl_permanant_mapped)
> +		return ioremap((unsigned long)phys, size);
> +	else
> +		return arch_early_ioremap((unsigned long)phys, size);
> +}
> +
> +static void sfi_unmap_memory(void __iomem *virt, u32 size)
> +{
> +	if (!virt || !size)
> +		return;
> +
> +	if (sfi_tbl_permanant_mapped)
> +		iounmap(virt);
> +	else
> +		arch_early_iounmap(virt, size);
> +}
> +

That's a disgusting facility. Should be separated out ...

> +static void sfi_print_table_header(u32 address,
> +			struct sfi_table_header *header)
> +{
> +	pr_info(PREFIX
> +		"%4.4s %08lX, %04X (r%d %6.6s %8.8s)\n",
> +		header->signature, (unsigned long)address,
> +		header->length, header->revision, header->oem_id,
> +		header->oem_table_id);
> +}

Why do we need the type cast above?

> +
> +static u8 sfi_checksum_table(u8 *buffer, u32 length)
> +{
> +	u8 sum = 0;
> +
> +	while (length--)
> +		sum += *buffer++;
> +	return sum;
> +}
> +
> +/* Verifies if the table checksums is zero */
> +static int sfi_tb_verify_checksum(struct sfi_table_header *table, u32 length)
> +{
> +	u8 checksum;
> +
> +	checksum = sfi_checksum_table((u8 *)table, length);

Why not declare sfi_checksum_table() with a void * input type 
instead and lose the cast above? That way a potential source of bugs 
gets found. (say accidentally passing in an 'address' to the 
function instead of a table pointer)

> +	if (checksum) {
> +		pr_warning(PREFIX
> +			"Incorrect checksum in table [%4.4s] -  %2.2X,"
> +			" should be %2.2X\n", table->signature,
> +			table->checksum, (u8)(table->checksum - checksum));
> +		return -1;
> +	}
> +	return 0;
> +}
> +
> + /* find the right table based on signaure, return the mapped table */
> +int sfi_get_table(char *signature, char *oem_id, char *oem_table_id,
> +	unsigned int flags, struct sfi_table_header **out_table)
> +{
> +	struct sfi_table_desc *tdesc;
> +	struct sfi_table_header *th;
> +	u32 i;
> +
> +	if (!signature || !out_table)
> +		return -1;
> +
> +	/* Walk the global SFI table list */
> +	for (i = 0; i < sfi_tblist.count; i++) {
> +		tdesc = &sfi_tblist.tables[i];
> +		th = &tdesc->header;
> +
> +		if ((flags & SFI_ACPI_TABLE) != (tdesc->flags & SFI_ACPI_TABLE))
> +			continue;
> +
> +		if (strncmp(th->signature, signature, SFI_SIGNATURE_SIZE))
> +			continue;
> +
> +		if (oem_id && strncmp(th->oem_id, oem_id, SFI_OEM_ID_SIZE))
> +			continue;
> +
> +		if (oem_table_id && strncmp(th->oem_table_id, oem_table_id,
> +			SFI_OEM_TABLE_ID_SIZE))
> +			continue;
> +
> +		if (!tdesc->pointer) {
> +			tdesc->pointer = sfi_map_memory(tdesc->address,
> +							th->length);
> +			if (!tdesc->pointer)
> +				return -ENOMEM;
> +		}
> +		*out_table = tdesc->pointer;
> +
> +		if (!sfi_tbl_permanant_mapped)
> +			tdesc->pointer = NULL;
> +
> +		return 0;
> +	}
> +
> +	return -1;
> +}
> +
> +void sfi_put_table(struct sfi_table_header *table)
> +{
> +	if (!sfi_tbl_permanant_mapped)
> +		sfi_unmap_memory(table, table->length);
> +}
> +
> +/* find table with signature, run handler on it */
> +int sfi_table_parse(char *signature, char *oem_id, char* oem_table_id,
> +	unsigned int flags, sfi_table_handler handler)
> +{
> +	int ret = 0;
> +	struct sfi_table_header *table = NULL;
> +
> +	if (!handler)
> +		return -EINVAL;
> +
> +	sfi_get_table(signature, oem_id, oem_table_id, flags, &table);
> +	if (!table)
> +		return -1;

the error return is a bit unclean here. First we use -EINVAL, then 
-1 - which is -EPERM which doesnt make sense. I'd suggest to return 
-EINVAL or -ENOTFOUND instead of -1 - not mix the return codes like 
that.

> +
> +	ret = handler(table);
> +	sfi_put_table(table);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(sfi_table_parse);
> +
> +void sfi_tb_install_table(u64 addr, u32 flags)
> +{
> +	struct sfi_table_header *table;
> +	u32 length;
> +
> +	/* only map table header before knowing actual length */
> +	table = sfi_map_memory(addr, sizeof(struct sfi_table_header));
> +	if (!table)
> +		return;
> +
> +	length = table->length;
> +	sfi_unmap_memory(table, sizeof(struct sfi_table_header));
> +
> +	table = sfi_map_memory(addr, length);
> +	if (!table)
> +		return;
> +
> +	if (sfi_tb_verify_checksum(table, length))
> +		goto unmap_and_exit;
> +
> +	/* Initialize sfi_tblist entry */
> +	sfi_tblist.tables[sfi_tblist.count].flags = flags;
> +	sfi_tblist.tables[sfi_tblist.count].address = addr;
> +	sfi_tblist.tables[sfi_tblist.count].pointer = NULL;
> +	memcpy(&sfi_tblist.tables[sfi_tblist.count].header,
> +		table, sizeof(struct sfi_table_header));
> +
> +	sfi_print_table_header(addr, table);
> +	sfi_tblist.count++;
> +
> +unmap_and_exit:
> +	sfi_unmap_memory(table, length);
> +	return;
> +}
> +
> +/*
> + * Copy system table and associated table headers to internal format
> + */
> +static int __init
> +sfi_tb_parse_syst(unsigned long syst_addr)
> +{
> +	struct sfi_table_simple *syst;
> +	struct sfi_table_header *table;
> +	u64 *paddr;
> +	u32 length, tbl_cnt;
> +	int status;
> +	int i;
> +
> +	/* 1. map and get the total length of SYST */
> +	syst = sfi_map_memory(syst_addr, sizeof(struct sfi_table_simple));
> +	if (!syst)
> +		return -ENOMEM;
> +
> +	sfi_print_table_header(syst_addr, (struct sfi_table_header *)syst);
> +	table = (struct sfi_table_header *)syst;
> +	length = table->length;
> +	sfi_unmap_memory(syst, sizeof(struct sfi_table_simple));
> +
> +	/* 2. remap/verify the SYST and parse the number of entry */
> +	syst = sfi_map_memory(syst_addr, length);
> +	if (!syst)
> +		return -ENOMEM;
> +
> +	table = (struct sfi_table_header *)syst;
> +	status = sfi_tb_verify_checksum(table, length);
> +	if (status) {
> +		pr_err(PREFIX "SYST checksum error!!\n");
> +		sfi_unmap_memory(table, length);
> +		return status;
> +	}
> +
> +	/* Calculate the number of tables */
> +	tbl_cnt = (length - sizeof(struct sfi_table_header)) / sizeof(u64);
> +	paddr = (u64 *) syst->pentry;
> +
> +	sfi_tblist.count = 1;
> +	sfi_tblist.tables[0].address = syst_addr;
> +	sfi_tblist.tables[0].pointer = NULL;
> +	memcpy(&sfi_tblist.tables[0].header,
> +		syst, sizeof(struct sfi_table_header));
> +
> +	/* 3. save all tables info to the global sfi_tblist structure */
> +	for (i = 1; i <= tbl_cnt; i++)
> +		sfi_tb_install_table(*paddr++, 0);
> +
> +	sfi_unmap_memory(syst, length);
> +
> +	return 0;
> +}
> +
> +
> +/*
> + * The OS finds the System Table by searching 16-byte boundaries between physical
> + * address 0x000E0000 and 0x000FFFFF. The OS shall search this region starting at the
> + * low address and shall stop searching when the 1st valid SFI System Table is found.

(Way-) overlong lines here.

> + */
> +static __init unsigned long sfi_find_syst(void)
> +{
> +	unsigned long offset, len;
> +	void *start;
> +
> +	len = SFI_SYST_SEARCH_END - SFI_SYST_SEARCH_BEGIN;
> +	start = sfi_map_memory(SFI_SYST_SEARCH_BEGIN, len);
> +	if (!start)
> +		return 0;
> +
> +	for (offset = 0; offset < len; offset += 16) {
> +		struct sfi_table_header *syst;
> +
> +		syst = (struct sfi_table_header *)(start + offset);

No need for the cast here - void pointers are unitype.

> +
> +		if (strncmp(syst->signature, SFI_SIG_SYST, SFI_SIGNATURE_SIZE))
> +				continue;

(one too many tabs)

> +
> +		if (!sfi_tb_verify_checksum(syst, syst->length)) {
> +			sfi_unmap_memory(start, len);
> +			return SFI_SYST_SEARCH_BEGIN + offset;
> +		}
> +	}
> +
> +	sfi_unmap_memory(start, len);
> +	return 0;
> +}
> +
> +int __init sfi_table_init(void)
> +{
> +	unsigned long syst_paddr;
> +	int status;
> +
> +	/* set up the SFI table array */
> +	sfi_tblist.tables = sfi_initial_tables;
> +	sfi_tblist.size = SFI_MAX_TABLES;
> +
> +	syst_paddr = sfi_find_syst();
> +	if (!syst_paddr) {
> +		pr_warning(PREFIX "No system table\n");
> +		goto err_exit;
> +	}
> +
> +	status = sfi_tb_parse_syst(syst_paddr);
> +	if (status)
> +		goto err_exit;
> +
> +	return 0;
> +err_exit:
> +	disable_sfi();
> +	return -1;
> +}
> +
> +static void sfi_realloc_tblist(void)
> +{
> +	int size;
> +	struct sfi_table_desc *table;
> +
> +	size = (sfi_tblist.count + 8) * sizeof(struct sfi_table_desc);

magic, unexplained 8.

> +	table = kzalloc(size, GFP_KERNEL);
> +	if (!table) {
> +		disable_sfi();
> +		return;
> +	}
> +
> +	memcpy(table, sfi_tblist.tables,
> +		sfi_tblist.count * sizeof(struct sfi_table_desc));
> +	sfi_tblist.tables = table;
> +	return;
> +}
> +
> +int __init sfi_init(void)
> +{
> +	if(!acpi_disabled){
> +		disable_sfi();
> +		return -1;
> +	}
> +
> +	if(sfi_disabled)
> +		return -1;

Coding style problems.

> +
> +	pr_info(PREFIX "Simple Firmware Interface v0.5\n");
> +
> +	if (sfi_table_init())
> +		return -1;
> +
> +	return sfi_platform_init();
> +}
> +/* after most of the system is up, abandon the static array */
> +void __init sfi_init_late(void)
> +{
> +	if (sfi_disabled)
> +		return;
> +	sfi_tbl_permanant_mapped = 1;
> +	sfi_realloc_tblist();
> +}
> +
> +static int __init sfi_parse_cmdline(char *arg)
> +{
> +	if (!arg)
> +		return -EINVAL;
> +
> +	if (!strcmp(arg, "off"))
> +		sfi_disabled = 1;
> +
> +	return 0;
> +}
> +early_param("sfi", sfi_parse_cmdline);
> diff --git a/drivers/sfi/sfi_core.h b/drivers/sfi/sfi_core.h
> new file mode 100644
> index 0000000..36703b0
> --- /dev/null
> +++ b/drivers/sfi/sfi_core.h
> @@ -0,0 +1,63 @@
> +/* sfi_core.h Simple Firmware Interface, internal header */
> +
> +/*
> + * Copyright (C) 2009, Intel Corp.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions, and the following disclaimer,
> + *    without modification.
> + * 2. Redistributions in binary form must reproduce at minimum a disclaimer
> + *    substantially similar to the "NO WARRANTY" disclaimer below
> + *    ("Disclaimer") and any redistribution must be conditioned upon
> + *    including a substantially similar Disclaimer requirement for further
> + *    binary redistribution.
> + * 3. Neither the names of the above-listed copyright holders nor the names
> + *    of any contributors may be used to endorse or promote products derived
> + *    from this software without specific prior written permission.
> + *
> + * Alternatively, this software may be distributed under the terms of the
> + * GNU General Public License ("GPL") version 2 as published by the Free
> + * Software Foundation.
> + *
> + * NO WARRANTY
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
> + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
> + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGES.
> + */
> +
> +struct sfi_table_desc {
> +	struct sfi_table_header header;	/* copy of the headef info */

s/headef/header

> +	struct sfi_table_header *pointer;
> +	u64 address;
> +	u32 flags;
> +};
> +
> +/* SFI internal root SYSTem table */
> +struct sfi_internal_syst {
> +	struct sfi_table_desc *tables;
> +	u32 count;
> +	u32 size;
> +};

i'd suggest using the structure definition style you use in 
arch/x86/kernel/sfi.c:

> +struct sfi_table_desc {
> +	struct sfi_table_header		header;	/* copy of the headef info */
> +	struct sfi_table_header		*pointer;
> +	u64				address;
> +	u32				flags;
> +};


> +
> +extern int sfi_get_table(char *signature, char *oem_id, char *oem_table_id,
> +	uint flags, struct sfi_table_header **out_table);
> +extern void sfi_put_table(struct sfi_table_header *table);
> +
> +extern int sfi_acpi_init(void);
> +extern struct sfi_internal_syst sfi_tblist;
> +void sfi_tb_install_table(u64 address, u32 flags);
> +
> +#define SFI_ACPI_TABLE	1

In general, nice stuff - basically SFI is cleanly implemented ACPI 
tables without any of the run-code-in-acpi-tables complications, 
right?

	Ingo

  reply	other threads:[~2009-06-23  7:57 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-06-23  7:13 [RFC/PATCH 2.6.32] Simple Firmware Interface (SFI): initial support Len Brown
2009-06-23  7:13 ` [PATCH 1/8] SFI: Simple Firmware Interface - new Linux sub-system Len Brown
2009-06-23  7:14   ` [PATCH 2/8] SFI: include/linux/sfi.h Len Brown
2009-06-23  7:28     ` Ingo Molnar
2009-06-23  7:47       ` Feng Tang
2009-06-23  8:00         ` Ingo Molnar
2009-06-23  8:02           ` Feng Tang
2009-06-23  8:09             ` Ingo Molnar
2009-06-23 15:14               ` H. Peter Anvin
2009-06-30 21:57       ` Andrew Morton
2009-06-30 21:59         ` Ingo Molnar
2009-06-23  9:06     ` Sam Ravnborg
2009-06-23 15:52       ` Feng Tang
2009-06-23 19:26         ` Sam Ravnborg
2009-06-23  7:14   ` [PATCH 3/8] SFI: core support Len Brown
2009-06-23  7:56     ` Ingo Molnar [this message]
2009-06-23  8:32       ` Feng Tang
2009-06-23  9:03         ` Ingo Molnar
2009-06-23  9:15           ` Feng Tang
2009-06-23 17:20       ` Len Brown
2009-06-23 19:20         ` Ingo Molnar
2009-06-23 12:32     ` Andi Kleen
2009-06-23 16:57       ` Len Brown
2009-06-24  3:34       ` Feng Tang
2009-06-24  7:12         ` Andi Kleen
2009-06-24  7:40           ` Feng Tang
2009-06-24  7:55             ` Andi Kleen
2009-06-23  7:14   ` [PATCH 4/8] SFI: Hook boot-time initialization Len Brown
2009-06-23  7:14   ` [PATCH 5/8] SFI: Hook e820 memory map initialization Len Brown
2009-06-23  7:14   ` [PATCH 6/8] SFI: add ACPI extensions Len Brown
2009-06-23 12:18     ` Andi Kleen
2009-06-23 16:51       ` Len Brown
2009-06-23  7:14   ` [PATCH 7/8] SFI, PCI: Hook MMCONFIG Len Brown
2009-06-23  7:14   ` [PATCH 8/8] SFI: expose IO-APIC routines to SFI, not just ACPI Len Brown
2009-06-23  7:58     ` Ingo Molnar
2009-06-23  7:23   ` [PATCH 1/8] SFI: Simple Firmware Interface - new Linux sub-system Ingo Molnar
2009-06-23 18:31 ` [RFC/PATCH 2.6.32] Simple Firmware Interface (SFI): initial support Matthew Garrett
2009-06-23 18:41   ` Len Brown
2009-06-22 19:43     ` Pavel Machek
2009-06-24 21:13       ` Len Brown
2009-07-11 22:02         ` Pavel Machek
2009-07-13  3:25           ` [SFI-devel] " Peter Stuge
2009-06-23 18:51     ` Matthew Garrett
2009-06-23 20:00       ` Len Brown
2009-06-23 20:23         ` Matthew Garrett
2009-06-23 20:45           ` Matthew Garrett
2009-06-23 21:23             ` Alan Cox
2009-06-23 22:34               ` Len Brown
2009-06-23 22:20             ` Len Brown
2009-06-23 22:56               ` Matthew Garrett
2009-06-23 23:00               ` [SFI-devel] " Justen, Jordan L
2009-06-24  0:35                 ` Len Brown
2009-06-23 21:33           ` Len Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090623075643.GC6397@elte.hu \
    --to=mingo@elte.hu \
    --cc=akpm@linux-foundation.org \
    --cc=feng.tang@intel.com \
    --cc=hpa@zytor.com \
    --cc=len.brown@intel.com \
    --cc=lenb@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sfi-devel@simplefirmware.org \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    --cc=yinghai@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.