* [PATCH] ACPI : RSDT is forced to be used when 32/64X address mismatch in FADT
@ 2008-04-18 10:41 Zhao Yakui
2008-04-18 11:29 ` Thomas Renninger
0 siblings, 1 reply; 7+ messages in thread
From: Zhao Yakui @ 2008-04-18 10:41 UTC (permalink / raw)
To: lenb; +Cc: linux-acpi
Subject: ACPI: RSDT is forced to be used when 32/64X address mismatch in FADT
>From : Zhao Yakui <yakui.zhao@intel.com>
On some laptops 32/64x address mismatches in FADT when XSDT is used,
which will cause some potential problem. In such cases the RSDT is
used instead of XSDT.
http://bugzilla.kernel.org/show_bug.cgi?id=8246
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
---
drivers/acpi/tables/tbfadt.c | 46 +++++++++++++++++++++++++++++++-----------
drivers/acpi/tables/tbutils.c | 28 +++++++++++++++++++++++--
include/acpi/actables.h | 4 +--
3 files changed, 63 insertions(+), 15 deletions(-)
Index: linux-2.6/drivers/acpi/tables/tbutils.c
===================================================================
--- linux-2.6.orig/drivers/acpi/tables/tbutils.c
+++ linux-2.6/drivers/acpi/tables/tbutils.c
@@ -404,9 +404,22 @@ acpi_tb_parse_root_table(acpi_physical_a
u32 length;
u8 *table_entry;
acpi_status status;
+ int rsdt_forced;
ACPI_FUNCTION_TRACE(tb_parse_root_table);
+ rsdt_forced = 0;
+
+rsdt_retry:
+ if (rsdt_forced) {
+ /*
+ * When rsdt is forced to be used, it is necessary to
+ * reinitialize the acpi_gbl_root_table_list.
+ */
+ for (i = 0; i < acpi_gbl_root_table_list.count; i++)
+ ACPI_MEMSET(&(acpi_gbl_root_table_list.tables[i]),
+ 0, sizeof(struct acpi_table_desc));
+ }
/*
* Map the entire RSDP and extract the address of the RSDT or XSDT
*/
@@ -421,7 +434,8 @@ acpi_tb_parse_root_table(acpi_physical_a
/* Differentiate between RSDT and XSDT root tables */
- if (rsdp->revision > 1 && rsdp->xsdt_physical_address) {
+ if (rsdp->revision > 1 && rsdp->xsdt_physical_address
+ && !rsdt_forced) {
/*
* Root table is an XSDT (64-bit physical addresses). We must use the
* XSDT if the revision is > 1 and the XSDT pointer is present, as per
@@ -550,7 +564,17 @@ acpi_tb_parse_root_table(acpi_physical_a
if (ACPI_COMPARE_NAME
(&acpi_gbl_root_table_list.tables[i].signature,
ACPI_SIG_FADT)) {
- acpi_tb_parse_fadt(i, flags);
+ status = acpi_tb_parse_fadt(i, flags);
+ if (ACPI_FAILURE(status) && !rsdt_forced) {
+ /*
+ * If FADT has some errors and XSDT is used,
+ * rsdt will be tried.
+ */
+ ACPI_WARNING((AE_INFO, "FADT has errors. "
+ "RSDT will be used instead"));
+ rsdt_forced = 1;
+ goto rsdt_retry;
+ }
}
}
Index: linux-2.6/include/acpi/actables.h
===================================================================
--- linux-2.6.orig/include/acpi/actables.h
+++ linux-2.6/include/acpi/actables.h
@@ -49,9 +49,9 @@ acpi_status acpi_allocate_root_table(u32
/*
* tbfadt - FADT parse/convert/validate
*/
-void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags);
+acpi_status acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags);
-void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length);
+acpi_status acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length);
/*
* tbfind - find ACPI table
Index: linux-2.6/drivers/acpi/tables/tbfadt.c
===================================================================
--- linux-2.6.orig/drivers/acpi/tables/tbfadt.c
+++ linux-2.6/drivers/acpi/tables/tbfadt.c
@@ -54,7 +54,7 @@ acpi_tb_init_generic_address(struct acpi
static void acpi_tb_convert_fadt(void);
-static void acpi_tb_validate_fadt(void);
+static acpi_status acpi_tb_validate_fadt(void);
/* Table for conversion of FADT to common internal format and FADT validation */
@@ -148,17 +148,18 @@ acpi_tb_init_generic_address(struct acpi
* PARAMETERS: table_index - Index for the FADT
* Flags - Flags
*
- * RETURN: None
+ * RETURN: status
*
* DESCRIPTION: Initialize the FADT, DSDT and FACS tables
* (FADT contains the addresses of the DSDT and FACS)
*
******************************************************************************/
-void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags)
+acpi_status acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags)
{
u32 length;
struct acpi_table_header *table;
+ acpi_status status;
/*
* The FADT has multiple versions with different lengths,
@@ -173,7 +174,7 @@ void acpi_tb_parse_fadt(acpi_native_uint
acpi_os_map_memory(acpi_gbl_root_table_list.tables[table_index].
address, length);
if (!table) {
- return;
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
/*
@@ -184,7 +185,7 @@ void acpi_tb_parse_fadt(acpi_native_uint
/* Obtain a local copy of the FADT in common ACPI 2.0+ format */
- acpi_tb_create_local_fadt(table, length);
+ status = acpi_tb_create_local_fadt(table, length);
/* All done with the real FADT, unmap it */
@@ -197,6 +198,8 @@ void acpi_tb_parse_fadt(acpi_native_uint
acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs,
flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS);
+
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
@@ -206,7 +209,7 @@ void acpi_tb_parse_fadt(acpi_native_uint
* PARAMETERS: Table - Pointer to BIOS FADT
* Length - Length of the table
*
- * RETURN: None
+ * RETURN: status
*
* DESCRIPTION: Get a local copy of the FADT and convert it to a common format.
* Performs validation on some important FADT fields.
@@ -215,9 +218,10 @@ void acpi_tb_parse_fadt(acpi_native_uint
*
******************************************************************************/
-void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
+acpi_status
+acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
{
-
+ acpi_status status;
/*
* Check if the FADT is larger than the largest table that we expect
* (the ACPI 2.0/3.0 version). If so, truncate the table, and issue
@@ -244,7 +248,9 @@ void acpi_tb_create_local_fadt(struct ac
* 2) Validate some of the important values within the FADT
*/
acpi_tb_convert_fadt();
- acpi_tb_validate_fadt();
+ status = acpi_tb_validate_fadt();
+
+ return_ACPI_STATUS(status);
}
/*******************************************************************************
@@ -377,7 +383,7 @@ static void acpi_tb_convert_fadt(void)
*
* PARAMETERS: Table - Pointer to the FADT to be validated
*
- * RETURN: None
+ * RETURN: status
*
* DESCRIPTION: Validate various important fields within the FADT. If a problem
* is found, issue a message, but no status is returned.
@@ -391,12 +397,16 @@ static void acpi_tb_convert_fadt(void)
*
******************************************************************************/
-static void acpi_tb_validate_fadt(void)
+static acpi_status acpi_tb_validate_fadt(void)
{
u32 *address32;
struct acpi_generic_address *address64;
u8 length;
acpi_native_uint i;
+ acpi_status status;
+
+ /* The default status is AE_OK */
+ status = AE_OK;
/* Examine all of the 64-bit extended address fields (X fields) */
@@ -420,6 +430,12 @@ static void acpi_tb_validate_fadt(void)
* Both the address and length must be non-zero.
*/
if (!address64->address || !length) {
+ /*
+ * Is it necessary to break the loop when the
+ * required filed has zero address or length?
+ * If it is required, please fix me.
+ */
+ status = AE_ERROR;
ACPI_ERROR((AE_INFO,
"Required field \"%s\" has zero address and/or length: %8.8X%8.8X/%X",
fadt_info_table[i].name,
@@ -447,10 +463,18 @@ static void acpi_tb_validate_fadt(void)
if (address64->address && *address32 &&
(address64->address != (u64) * address32)) {
+ /*
+ * Is it necessary to break the loop when the 32/64
+ * address mismatches ?
+ * If it is required, please fix me.
+ */
+ status = AE_ERROR;
ACPI_ERROR((AE_INFO,
"32/64X address mismatch in \"%s\": [%8.8X] [%8.8X%8.8X], using 64X",
fadt_info_table[i].name, *address32,
ACPI_FORMAT_UINT64(address64->address)));
}
}
+
+ return_ACPI_STATUS(status);
}
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH] ACPI : RSDT is forced to be used when 32/64X address mismatch in FADT 2008-04-18 10:41 [PATCH] ACPI : RSDT is forced to be used when 32/64X address mismatch in FADT Zhao Yakui @ 2008-04-18 11:29 ` Thomas Renninger 2008-04-18 13:35 ` Thomas Renninger 2008-04-22 8:46 ` Zhao Yakui 0 siblings, 2 replies; 7+ messages in thread From: Thomas Renninger @ 2008-04-18 11:29 UTC (permalink / raw) To: Zhao Yakui; +Cc: lenb, linux-acpi On Fri, 2008-04-18 at 18:41 +0800, Zhao Yakui wrote: > Subject: ACPI: RSDT is forced to be used when 32/64X address mismatch in FADT > >From : Zhao Yakui <yakui.zhao@intel.com> > > On some laptops 32/64x address mismatches in FADT when XSDT is used, > which will cause some potential problem. In such cases the RSDT is > used instead of XSDT. This sounds wrong. It sounds like the system got tested using the RSDT (probably on Windows). Nowadays, the XSDT will be the more tested table and RSDT entries are likely to be wrong. If you get a mismatch on a more recent machines it's likely that you choose the wrong table by taking the RSDT. IMO these machines (if there are not much) should be blacklisted to use the RSDT using dmi info (which should already be available at that time). Thomas > > http://bugzilla.kernel.org/show_bug.cgi?id=8246 > > Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> > Signed-off-by: Zhang Rui <rui.zhang@intel.com> > > --- > drivers/acpi/tables/tbfadt.c | 46 +++++++++++++++++++++++++++++++----------- > drivers/acpi/tables/tbutils.c | 28 +++++++++++++++++++++++-- > include/acpi/actables.h | 4 +-- > 3 files changed, 63 insertions(+), 15 deletions(-) > > Index: linux-2.6/drivers/acpi/tables/tbutils.c > =================================================================== > --- linux-2.6.orig/drivers/acpi/tables/tbutils.c > +++ linux-2.6/drivers/acpi/tables/tbutils.c > @@ -404,9 +404,22 @@ acpi_tb_parse_root_table(acpi_physical_a > u32 length; > u8 *table_entry; > acpi_status status; > + int rsdt_forced; > > ACPI_FUNCTION_TRACE(tb_parse_root_table); > > + rsdt_forced = 0; > + > +rsdt_retry: > + if (rsdt_forced) { > + /* > + * When rsdt is forced to be used, it is necessary to > + * reinitialize the acpi_gbl_root_table_list. > + */ > + for (i = 0; i < acpi_gbl_root_table_list.count; i++) > + ACPI_MEMSET(&(acpi_gbl_root_table_list.tables[i]), > + 0, sizeof(struct acpi_table_desc)); > + } > /* > * Map the entire RSDP and extract the address of the RSDT or XSDT > */ > @@ -421,7 +434,8 @@ acpi_tb_parse_root_table(acpi_physical_a > > /* Differentiate between RSDT and XSDT root tables */ > > - if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { > + if (rsdp->revision > 1 && rsdp->xsdt_physical_address > + && !rsdt_forced) { > /* > * Root table is an XSDT (64-bit physical addresses). We must use the > * XSDT if the revision is > 1 and the XSDT pointer is present, as per > @@ -550,7 +564,17 @@ acpi_tb_parse_root_table(acpi_physical_a > if (ACPI_COMPARE_NAME > (&acpi_gbl_root_table_list.tables[i].signature, > ACPI_SIG_FADT)) { > - acpi_tb_parse_fadt(i, flags); > + status = acpi_tb_parse_fadt(i, flags); > + if (ACPI_FAILURE(status) && !rsdt_forced) { > + /* > + * If FADT has some errors and XSDT is used, > + * rsdt will be tried. > + */ > + ACPI_WARNING((AE_INFO, "FADT has errors. " > + "RSDT will be used instead")); > + rsdt_forced = 1; > + goto rsdt_retry; > + } > } > } > > Index: linux-2.6/include/acpi/actables.h > =================================================================== > --- linux-2.6.orig/include/acpi/actables.h > +++ linux-2.6/include/acpi/actables.h > @@ -49,9 +49,9 @@ acpi_status acpi_allocate_root_table(u32 > /* > * tbfadt - FADT parse/convert/validate > */ > -void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags); > +acpi_status acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags); > > -void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length); > +acpi_status acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length); > > /* > * tbfind - find ACPI table > Index: linux-2.6/drivers/acpi/tables/tbfadt.c > =================================================================== > --- linux-2.6.orig/drivers/acpi/tables/tbfadt.c > +++ linux-2.6/drivers/acpi/tables/tbfadt.c > @@ -54,7 +54,7 @@ acpi_tb_init_generic_address(struct acpi > > static void acpi_tb_convert_fadt(void); > > -static void acpi_tb_validate_fadt(void); > +static acpi_status acpi_tb_validate_fadt(void); > > /* Table for conversion of FADT to common internal format and FADT validation */ > > @@ -148,17 +148,18 @@ acpi_tb_init_generic_address(struct acpi > * PARAMETERS: table_index - Index for the FADT > * Flags - Flags > * > - * RETURN: None > + * RETURN: status > * > * DESCRIPTION: Initialize the FADT, DSDT and FACS tables > * (FADT contains the addresses of the DSDT and FACS) > * > ******************************************************************************/ > > -void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) > +acpi_status acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) > { > u32 length; > struct acpi_table_header *table; > + acpi_status status; > > /* > * The FADT has multiple versions with different lengths, > @@ -173,7 +174,7 @@ void acpi_tb_parse_fadt(acpi_native_uint > acpi_os_map_memory(acpi_gbl_root_table_list.tables[table_index]. > address, length); > if (!table) { > - return; > + return_ACPI_STATUS(AE_NO_MEMORY); > } > > /* > @@ -184,7 +185,7 @@ void acpi_tb_parse_fadt(acpi_native_uint > > /* Obtain a local copy of the FADT in common ACPI 2.0+ format */ > > - acpi_tb_create_local_fadt(table, length); > + status = acpi_tb_create_local_fadt(table, length); > > /* All done with the real FADT, unmap it */ > > @@ -197,6 +198,8 @@ void acpi_tb_parse_fadt(acpi_native_uint > > acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, > flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); > + > + return_ACPI_STATUS(status); > } > > /******************************************************************************* > @@ -206,7 +209,7 @@ void acpi_tb_parse_fadt(acpi_native_uint > * PARAMETERS: Table - Pointer to BIOS FADT > * Length - Length of the table > * > - * RETURN: None > + * RETURN: status > * > * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. > * Performs validation on some important FADT fields. > @@ -215,9 +218,10 @@ void acpi_tb_parse_fadt(acpi_native_uint > * > ******************************************************************************/ > > -void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) > +acpi_status > +acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) > { > - > + acpi_status status; > /* > * Check if the FADT is larger than the largest table that we expect > * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue > @@ -244,7 +248,9 @@ void acpi_tb_create_local_fadt(struct ac > * 2) Validate some of the important values within the FADT > */ > acpi_tb_convert_fadt(); > - acpi_tb_validate_fadt(); > + status = acpi_tb_validate_fadt(); > + > + return_ACPI_STATUS(status); > } > > /******************************************************************************* > @@ -377,7 +383,7 @@ static void acpi_tb_convert_fadt(void) > * > * PARAMETERS: Table - Pointer to the FADT to be validated > * > - * RETURN: None > + * RETURN: status > * > * DESCRIPTION: Validate various important fields within the FADT. If a problem > * is found, issue a message, but no status is returned. > @@ -391,12 +397,16 @@ static void acpi_tb_convert_fadt(void) > * > ******************************************************************************/ > > -static void acpi_tb_validate_fadt(void) > +static acpi_status acpi_tb_validate_fadt(void) > { > u32 *address32; > struct acpi_generic_address *address64; > u8 length; > acpi_native_uint i; > + acpi_status status; > + > + /* The default status is AE_OK */ > + status = AE_OK; > > /* Examine all of the 64-bit extended address fields (X fields) */ > > @@ -420,6 +430,12 @@ static void acpi_tb_validate_fadt(void) > * Both the address and length must be non-zero. > */ > if (!address64->address || !length) { > + /* > + * Is it necessary to break the loop when the > + * required filed has zero address or length? > + * If it is required, please fix me. > + */ > + status = AE_ERROR; > ACPI_ERROR((AE_INFO, > "Required field \"%s\" has zero address and/or length: %8.8X%8.8X/%X", > fadt_info_table[i].name, > @@ -447,10 +463,18 @@ static void acpi_tb_validate_fadt(void) > > if (address64->address && *address32 && > (address64->address != (u64) * address32)) { > + /* > + * Is it necessary to break the loop when the 32/64 > + * address mismatches ? > + * If it is required, please fix me. > + */ > + status = AE_ERROR; > ACPI_ERROR((AE_INFO, > "32/64X address mismatch in \"%s\": [%8.8X] [%8.8X%8.8X], using 64X", > fadt_info_table[i].name, *address32, > ACPI_FORMAT_UINT64(address64->address))); > } > } > + > + return_ACPI_STATUS(status); > } > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-acpi" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] ACPI : RSDT is forced to be used when 32/64X address mismatch in FADT 2008-04-18 11:29 ` Thomas Renninger @ 2008-04-18 13:35 ` Thomas Renninger 2008-04-19 4:24 ` Henrique de Moraes Holschuh 2008-04-22 8:46 ` Zhao Yakui 1 sibling, 1 reply; 7+ messages in thread From: Thomas Renninger @ 2008-04-18 13:35 UTC (permalink / raw) To: Zhao Yakui; +Cc: lenb, linux-acpi On Fri, 2008-04-18 at 13:29 +0200, Thomas Renninger wrote: > On Fri, 2008-04-18 at 18:41 +0800, Zhao Yakui wrote: > > Subject: ACPI: RSDT is forced to be used when 32/64X address mismatch in FADT > > >From : Zhao Yakui <yakui.zhao@intel.com> > > > > On some laptops 32/64x address mismatches in FADT when XSDT is used, > > which will cause some potential problem. In such cases the RSDT is > > used instead of XSDT. > This sounds wrong. > > It sounds like the system got tested using the RSDT (probably on > Windows). Nowadays, the XSDT will be the more tested table and RSDT > entries are likely to be wrong. If you get a mismatch on a more recent > machines it's likely that you choose the wrong table by taking the RSDT. > IMO these machines (if there are not much) should be blacklisted to use > the RSDT using dmi info (which should already be available at that > time). Just a guess, but I could imagine you can move the dmi blacklist from processor_idle (The bug states a ThinkPad R50?) to e.g. osl.c and set a global force_rsdt variable there (or whatever the implementation details could look like...): static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { { set_max_cstate, "IBM ThinkPad R40e", { DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), DMI_MATCH(DMI_BIOS_VERSION,"1SET70WW")}, (void *)1}, { set_max_cstate, "IBM ThinkPad R40e", { DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW")}, (void *)1}, { set_max_cstate, "IBM ThinkPad R40e", { ... } I'd take DMI_MATCH(DMI_BIOS_VERSION,"1SET") to match for all. These machines might be very similar (ThinkPad R40e is probably wrong as not the name, but the BIOS version which could be the same than for e.g. R50 is hit). I expect that C states are going to work if you take the right addresses for C-state triggering from the RSDT. Better let the reporter post dmi info and double check. Great that you (possibly) found the real cause. Thomas > Thomas > > > > http://bugzilla.kernel.org/show_bug.cgi?id=8246 > > > > Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> > > Signed-off-by: Zhang Rui <rui.zhang@intel.com> > > > > --- > > drivers/acpi/tables/tbfadt.c | 46 +++++++++++++++++++++++++++++++----------- > > drivers/acpi/tables/tbutils.c | 28 +++++++++++++++++++++++-- > > include/acpi/actables.h | 4 +-- > > 3 files changed, 63 insertions(+), 15 deletions(-) > > > > Index: linux-2.6/drivers/acpi/tables/tbutils.c > > =================================================================== > > --- linux-2.6.orig/drivers/acpi/tables/tbutils.c > > +++ linux-2.6/drivers/acpi/tables/tbutils.c > > @@ -404,9 +404,22 @@ acpi_tb_parse_root_table(acpi_physical_a > > u32 length; > > u8 *table_entry; > > acpi_status status; > > + int rsdt_forced; > > > > ACPI_FUNCTION_TRACE(tb_parse_root_table); > > > > + rsdt_forced = 0; > > + > > +rsdt_retry: > > + if (rsdt_forced) { > > + /* > > + * When rsdt is forced to be used, it is necessary to > > + * reinitialize the acpi_gbl_root_table_list. > > + */ > > + for (i = 0; i < acpi_gbl_root_table_list.count; i++) > > + ACPI_MEMSET(&(acpi_gbl_root_table_list.tables[i]), > > + 0, sizeof(struct acpi_table_desc)); > > + } > > /* > > * Map the entire RSDP and extract the address of the RSDT or XSDT > > */ > > @@ -421,7 +434,8 @@ acpi_tb_parse_root_table(acpi_physical_a > > > > /* Differentiate between RSDT and XSDT root tables */ > > > > - if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { > > + if (rsdp->revision > 1 && rsdp->xsdt_physical_address > > + && !rsdt_forced) { > > /* > > * Root table is an XSDT (64-bit physical addresses). We must use the > > * XSDT if the revision is > 1 and the XSDT pointer is present, as per > > @@ -550,7 +564,17 @@ acpi_tb_parse_root_table(acpi_physical_a > > if (ACPI_COMPARE_NAME > > (&acpi_gbl_root_table_list.tables[i].signature, > > ACPI_SIG_FADT)) { > > - acpi_tb_parse_fadt(i, flags); > > + status = acpi_tb_parse_fadt(i, flags); > > + if (ACPI_FAILURE(status) && !rsdt_forced) { > > + /* > > + * If FADT has some errors and XSDT is used, > > + * rsdt will be tried. > > + */ > > + ACPI_WARNING((AE_INFO, "FADT has errors. " > > + "RSDT will be used instead")); > > + rsdt_forced = 1; > > + goto rsdt_retry; > > + } > > } > > } > > > > Index: linux-2.6/include/acpi/actables.h > > =================================================================== > > --- linux-2.6.orig/include/acpi/actables.h > > +++ linux-2.6/include/acpi/actables.h > > @@ -49,9 +49,9 @@ acpi_status acpi_allocate_root_table(u32 > > /* > > * tbfadt - FADT parse/convert/validate > > */ > > -void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags); > > +acpi_status acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags); > > > > -void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length); > > +acpi_status acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length); > > > > /* > > * tbfind - find ACPI table > > Index: linux-2.6/drivers/acpi/tables/tbfadt.c > > =================================================================== > > --- linux-2.6.orig/drivers/acpi/tables/tbfadt.c > > +++ linux-2.6/drivers/acpi/tables/tbfadt.c > > @@ -54,7 +54,7 @@ acpi_tb_init_generic_address(struct acpi > > > > static void acpi_tb_convert_fadt(void); > > > > -static void acpi_tb_validate_fadt(void); > > +static acpi_status acpi_tb_validate_fadt(void); > > > > /* Table for conversion of FADT to common internal format and FADT validation */ > > > > @@ -148,17 +148,18 @@ acpi_tb_init_generic_address(struct acpi > > * PARAMETERS: table_index - Index for the FADT > > * Flags - Flags > > * > > - * RETURN: None > > + * RETURN: status > > * > > * DESCRIPTION: Initialize the FADT, DSDT and FACS tables > > * (FADT contains the addresses of the DSDT and FACS) > > * > > ******************************************************************************/ > > > > -void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) > > +acpi_status acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) > > { > > u32 length; > > struct acpi_table_header *table; > > + acpi_status status; > > > > /* > > * The FADT has multiple versions with different lengths, > > @@ -173,7 +174,7 @@ void acpi_tb_parse_fadt(acpi_native_uint > > acpi_os_map_memory(acpi_gbl_root_table_list.tables[table_index]. > > address, length); > > if (!table) { > > - return; > > + return_ACPI_STATUS(AE_NO_MEMORY); > > } > > > > /* > > @@ -184,7 +185,7 @@ void acpi_tb_parse_fadt(acpi_native_uint > > > > /* Obtain a local copy of the FADT in common ACPI 2.0+ format */ > > > > - acpi_tb_create_local_fadt(table, length); > > + status = acpi_tb_create_local_fadt(table, length); > > > > /* All done with the real FADT, unmap it */ > > > > @@ -197,6 +198,8 @@ void acpi_tb_parse_fadt(acpi_native_uint > > > > acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, > > flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); > > + > > + return_ACPI_STATUS(status); > > } > > > > /******************************************************************************* > > @@ -206,7 +209,7 @@ void acpi_tb_parse_fadt(acpi_native_uint > > * PARAMETERS: Table - Pointer to BIOS FADT > > * Length - Length of the table > > * > > - * RETURN: None > > + * RETURN: status > > * > > * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. > > * Performs validation on some important FADT fields. > > @@ -215,9 +218,10 @@ void acpi_tb_parse_fadt(acpi_native_uint > > * > > ******************************************************************************/ > > > > -void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) > > +acpi_status > > +acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) > > { > > - > > + acpi_status status; > > /* > > * Check if the FADT is larger than the largest table that we expect > > * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue > > @@ -244,7 +248,9 @@ void acpi_tb_create_local_fadt(struct ac > > * 2) Validate some of the important values within the FADT > > */ > > acpi_tb_convert_fadt(); > > - acpi_tb_validate_fadt(); > > + status = acpi_tb_validate_fadt(); > > + > > + return_ACPI_STATUS(status); > > } > > > > /******************************************************************************* > > @@ -377,7 +383,7 @@ static void acpi_tb_convert_fadt(void) > > * > > * PARAMETERS: Table - Pointer to the FADT to be validated > > * > > - * RETURN: None > > + * RETURN: status > > * > > * DESCRIPTION: Validate various important fields within the FADT. If a problem > > * is found, issue a message, but no status is returned. > > @@ -391,12 +397,16 @@ static void acpi_tb_convert_fadt(void) > > * > > ******************************************************************************/ > > > > -static void acpi_tb_validate_fadt(void) > > +static acpi_status acpi_tb_validate_fadt(void) > > { > > u32 *address32; > > struct acpi_generic_address *address64; > > u8 length; > > acpi_native_uint i; > > + acpi_status status; > > + > > + /* The default status is AE_OK */ > > + status = AE_OK; > > > > /* Examine all of the 64-bit extended address fields (X fields) */ > > > > @@ -420,6 +430,12 @@ static void acpi_tb_validate_fadt(void) > > * Both the address and length must be non-zero. > > */ > > if (!address64->address || !length) { > > + /* > > + * Is it necessary to break the loop when the > > + * required filed has zero address or length? > > + * If it is required, please fix me. > > + */ > > + status = AE_ERROR; > > ACPI_ERROR((AE_INFO, > > "Required field \"%s\" has zero address and/or length: %8.8X%8.8X/%X", > > fadt_info_table[i].name, > > @@ -447,10 +463,18 @@ static void acpi_tb_validate_fadt(void) > > > > if (address64->address && *address32 && > > (address64->address != (u64) * address32)) { > > + /* > > + * Is it necessary to break the loop when the 32/64 > > + * address mismatches ? > > + * If it is required, please fix me. > > + */ > > + status = AE_ERROR; > > ACPI_ERROR((AE_INFO, > > "32/64X address mismatch in \"%s\": [%8.8X] [%8.8X%8.8X], using 64X", > > fadt_info_table[i].name, *address32, > > ACPI_FORMAT_UINT64(address64->address))); > > } > > } > > + > > + return_ACPI_STATUS(status); > > } > > > > > > -- > > To unsubscribe from this list: send the line "unsubscribe linux-acpi" in > > the body of a message to majordomo@vger.kernel.org > > More majordomo info at http://vger.kernel.org/majordomo-info.html > > -- > To unsubscribe from this list: send the line "unsubscribe linux-acpi" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] ACPI : RSDT is forced to be used when 32/64X address mismatch in FADT 2008-04-18 13:35 ` Thomas Renninger @ 2008-04-19 4:24 ` Henrique de Moraes Holschuh 2008-04-21 10:07 ` Thomas Renninger 0 siblings, 1 reply; 7+ messages in thread From: Henrique de Moraes Holschuh @ 2008-04-19 4:24 UTC (permalink / raw) To: Thomas Renninger; +Cc: Zhao Yakui, lenb, linux-acpi On Fri, 18 Apr 2008, Thomas Renninger wrote: > I'd take DMI_MATCH(DMI_BIOS_VERSION,"1SET") to match for all. Agreed, if 1SET70 has a bug, all other versions of that BIOS before 70 probably have that bug too. > These machines might be very similar (ThinkPad R40e is probably wrong as > not the name, but the BIOS version which could be the same than for e.g. > R50 is hit). I expect that C states are going to work if you take the -EPARSE. The 1S BIOS *is* the R40e BIOS, and don't understand what you mean with the R50? The BIOS for the R50, T40, T41 and T42 as well as some R51 models is the same (BIOS 1R). -- "One disk to rule them all, One disk to find them. One disk to bring them all and in the darkness grind them. In the Land of Redmond where the shadows lie." -- The Silicon Valley Tarot Henrique Holschuh ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] ACPI : RSDT is forced to be used when 32/64X address mismatch in FADT 2008-04-19 4:24 ` Henrique de Moraes Holschuh @ 2008-04-21 10:07 ` Thomas Renninger 2008-04-21 14:39 ` Henrique de Moraes Holschuh 0 siblings, 1 reply; 7+ messages in thread From: Thomas Renninger @ 2008-04-21 10:07 UTC (permalink / raw) To: Henrique de Moraes Holschuh; +Cc: Zhao Yakui, lenb, linux-acpi On Sat, 2008-04-19 at 01:24 -0300, Henrique de Moraes Holschuh wrote: > On Fri, 18 Apr 2008, Thomas Renninger wrote: > > I'd take DMI_MATCH(DMI_BIOS_VERSION,"1SET") to match for all. > > Agreed, if 1SET70 has a bug, all other versions of that BIOS before 70 > probably have that bug too. > > > These machines might be very similar (ThinkPad R40e is probably wrong as > > not the name, but the BIOS version which could be the same than for e.g. > > R50 is hit). I expect that C states are going to work if you take the > > -EPARSE. The 1S BIOS *is* the R40e BIOS, and don't understand what you > mean with the R50? The BIOS for the R50, T40, T41 and T42 as well as > some R51 models is the same (BIOS 1R). Sorry, I should have been more detailed... - IIRC the physical HW address to switch to C2/C3 is provided through the FADT table. - For "1SET*" ThinkPad BIOSes, C-states are blacklisted as they freeze if C-states are invoked (see drivers/acpi/processor_idle.c). - This patch chooses an alternate FADT table if the content of the other table differs (either the one pointed to by XSDT or RSDT). - The machine which shows different contents of FADTs is a R50e: http://bugzilla.kernel.org/show_bug.cgi?id=8246 - While the bug was opened because of slow booting (due to wrong HW addresses accessed?), I could imagine Yakui has found the root cause why C-states didn't work on some older ThinkPads. -> It should be tested whether ThinkPads which have C-states blacklisted do work with the other FADT and the blacklist in drivers/acpi/processor_idle.c can be removed or what I meant, it can be moved/reused for a kind of force_rsdt flag... All this is theory and needs testing... I can try to find one of the older ThinkPad models... Thomas ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] ACPI : RSDT is forced to be used when 32/64X address mismatch in FADT 2008-04-21 10:07 ` Thomas Renninger @ 2008-04-21 14:39 ` Henrique de Moraes Holschuh 0 siblings, 0 replies; 7+ messages in thread From: Henrique de Moraes Holschuh @ 2008-04-21 14:39 UTC (permalink / raw) To: Thomas Renninger; +Cc: Zhao Yakui, lenb, linux-acpi, linux-thinkpad On Mon, 21 Apr 2008, Thomas Renninger wrote: > - IIRC the physical HW address to switch to C2/C3 is provided through > the FADT table. > - For "1SET*" ThinkPad BIOSes, C-states are blacklisted as they freeze > if C-states are invoked (see drivers/acpi/processor_idle.c). > - This patch chooses an alternate FADT table if the content of the > other table differs (either the one pointed to by XSDT or RSDT). > - The machine which shows different contents of FADTs is a R50e: > http://bugzilla.kernel.org/show_bug.cgi?id=8246 > - While the bug was opened because of slow booting (due to wrong HW > addresses accessed?), I could imagine Yakui has found the root cause > why C-states didn't work on some older ThinkPads. > > -> It should be tested whether ThinkPads which have C-states blacklisted > do work with the other FADT and the blacklist in > drivers/acpi/processor_idle.c can be removed or what I meant, it can be > moved/reused for a kind of force_rsdt flag... > > All this is theory and needs testing... > I can try to find one of the older ThinkPad models... This is really interesting, and I am sure that should you provide patches and instructions that users can easily apply to, say, 2.6.24.y, in an email to the linux-thinkpad ML describing what benefits should testing could have, you'll get some good testers. I've easily gotten a lot of the testing I needed done in the past by asking for help there. I have added linux-thinkpad to the CC, but I seriously recommend that you start a new thread there with a much more clear subject if you decide to ask for testers. It'd be good to also have a list of the thinkpad models currently blacklisted for functions that depend on the FADT, and thus which could get these functions back if the select-the-proper-FADT patch works on them. -- "One disk to rule them all, One disk to find them. One disk to bring them all and in the darkness grind them. In the Land of Redmond where the shadows lie." -- The Silicon Valley Tarot Henrique Holschuh ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] ACPI : RSDT is forced to be used when 32/64X address mismatch in FADT 2008-04-18 11:29 ` Thomas Renninger 2008-04-18 13:35 ` Thomas Renninger @ 2008-04-22 8:46 ` Zhao Yakui 1 sibling, 0 replies; 7+ messages in thread From: Zhao Yakui @ 2008-04-22 8:46 UTC (permalink / raw) To: trenn; +Cc: lenb, linux-acpi On Fri, 2008-04-18 at 13:29 +0200, Thomas Renninger wrote: > On Fri, 2008-04-18 at 18:41 +0800, Zhao Yakui wrote: > > Subject: ACPI: RSDT is forced to be used when 32/64X address mismatch in FADT > > >From : Zhao Yakui <yakui.zhao@intel.com> > > > > On some laptops 32/64x address mismatches in FADT when XSDT is used, > > which will cause some potential problem. In such cases the RSDT is > > used instead of XSDT. > This sounds wrong. > Thank you for caring this problem. > It sounds like the system got tested using the RSDT (probably on > Windows). Nowadays, the XSDT will be the more tested table and RSDT > entries are likely to be wrong. IMO. RSDT is still the more tested table and on many laptops the RSDT is used by Windows even when there exist both RSDT and XSDT. > If you get a mismatch on a more recent > machines it's likely that you choose the wrong table by taking the RSDT. > IMO these machines (if there are not much) should be blacklisted to use > the RSDT using dmi info (which should already be available at that > time). Of course the method your introduce is also OK. And we should add a global varible which is used to select RSDT or XSDT. But the parse of ACPI tables is realized in ACPICA. IMO it is inappropriate to add such variable referred by ACPICA. Best regards Yakui > Thomas > > > > http://bugzilla.kernel.org/show_bug.cgi?id=8246 > > > > Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> > > Signed-off-by: Zhang Rui <rui.zhang@intel.com> > > > > --- > > drivers/acpi/tables/tbfadt.c | 46 +++++++++++++++++++++++++++++++----------- > > drivers/acpi/tables/tbutils.c | 28 +++++++++++++++++++++++-- > > include/acpi/actables.h | 4 +-- > > 3 files changed, 63 insertions(+), 15 deletions(-) > > > > Index: linux-2.6/drivers/acpi/tables/tbutils.c > > =================================================================== > > --- linux-2.6.orig/drivers/acpi/tables/tbutils.c > > +++ linux-2.6/drivers/acpi/tables/tbutils.c > > @@ -404,9 +404,22 @@ acpi_tb_parse_root_table(acpi_physical_a > > u32 length; > > u8 *table_entry; > > acpi_status status; > > + int rsdt_forced; > > > > ACPI_FUNCTION_TRACE(tb_parse_root_table); > > > > + rsdt_forced = 0; > > + > > +rsdt_retry: > > + if (rsdt_forced) { > > + /* > > + * When rsdt is forced to be used, it is necessary to > > + * reinitialize the acpi_gbl_root_table_list. > > + */ > > + for (i = 0; i < acpi_gbl_root_table_list.count; i++) > > + ACPI_MEMSET(&(acpi_gbl_root_table_list.tables[i]), > > + 0, sizeof(struct acpi_table_desc)); > > + } > > /* > > * Map the entire RSDP and extract the address of the RSDT or XSDT > > */ > > @@ -421,7 +434,8 @@ acpi_tb_parse_root_table(acpi_physical_a > > > > /* Differentiate between RSDT and XSDT root tables */ > > > > - if (rsdp->revision > 1 && rsdp->xsdt_physical_address) { > > + if (rsdp->revision > 1 && rsdp->xsdt_physical_address > > + && !rsdt_forced) { > > /* > > * Root table is an XSDT (64-bit physical addresses). We must use the > > * XSDT if the revision is > 1 and the XSDT pointer is present, as per > > @@ -550,7 +564,17 @@ acpi_tb_parse_root_table(acpi_physical_a > > if (ACPI_COMPARE_NAME > > (&acpi_gbl_root_table_list.tables[i].signature, > > ACPI_SIG_FADT)) { > > - acpi_tb_parse_fadt(i, flags); > > + status = acpi_tb_parse_fadt(i, flags); > > + if (ACPI_FAILURE(status) && !rsdt_forced) { > > + /* > > + * If FADT has some errors and XSDT is used, > > + * rsdt will be tried. > > + */ > > + ACPI_WARNING((AE_INFO, "FADT has errors. " > > + "RSDT will be used instead")); > > + rsdt_forced = 1; > > + goto rsdt_retry; > > + } > > } > > } > > > > Index: linux-2.6/include/acpi/actables.h > > =================================================================== > > --- linux-2.6.orig/include/acpi/actables.h > > +++ linux-2.6/include/acpi/actables.h > > @@ -49,9 +49,9 @@ acpi_status acpi_allocate_root_table(u32 > > /* > > * tbfadt - FADT parse/convert/validate > > */ > > -void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags); > > +acpi_status acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags); > > > > -void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length); > > +acpi_status acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length); > > > > /* > > * tbfind - find ACPI table > > Index: linux-2.6/drivers/acpi/tables/tbfadt.c > > =================================================================== > > --- linux-2.6.orig/drivers/acpi/tables/tbfadt.c > > +++ linux-2.6/drivers/acpi/tables/tbfadt.c > > @@ -54,7 +54,7 @@ acpi_tb_init_generic_address(struct acpi > > > > static void acpi_tb_convert_fadt(void); > > > > -static void acpi_tb_validate_fadt(void); > > +static acpi_status acpi_tb_validate_fadt(void); > > > > /* Table for conversion of FADT to common internal format and FADT validation */ > > > > @@ -148,17 +148,18 @@ acpi_tb_init_generic_address(struct acpi > > * PARAMETERS: table_index - Index for the FADT > > * Flags - Flags > > * > > - * RETURN: None > > + * RETURN: status > > * > > * DESCRIPTION: Initialize the FADT, DSDT and FACS tables > > * (FADT contains the addresses of the DSDT and FACS) > > * > > ******************************************************************************/ > > > > -void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) > > +acpi_status acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) > > { > > u32 length; > > struct acpi_table_header *table; > > + acpi_status status; > > > > /* > > * The FADT has multiple versions with different lengths, > > @@ -173,7 +174,7 @@ void acpi_tb_parse_fadt(acpi_native_uint > > acpi_os_map_memory(acpi_gbl_root_table_list.tables[table_index]. > > address, length); > > if (!table) { > > - return; > > + return_ACPI_STATUS(AE_NO_MEMORY); > > } > > > > /* > > @@ -184,7 +185,7 @@ void acpi_tb_parse_fadt(acpi_native_uint > > > > /* Obtain a local copy of the FADT in common ACPI 2.0+ format */ > > > > - acpi_tb_create_local_fadt(table, length); > > + status = acpi_tb_create_local_fadt(table, length); > > > > /* All done with the real FADT, unmap it */ > > > > @@ -197,6 +198,8 @@ void acpi_tb_parse_fadt(acpi_native_uint > > > > acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, > > flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); > > + > > + return_ACPI_STATUS(status); > > } > > > > /******************************************************************************* > > @@ -206,7 +209,7 @@ void acpi_tb_parse_fadt(acpi_native_uint > > * PARAMETERS: Table - Pointer to BIOS FADT > > * Length - Length of the table > > * > > - * RETURN: None > > + * RETURN: status > > * > > * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. > > * Performs validation on some important FADT fields. > > @@ -215,9 +218,10 @@ void acpi_tb_parse_fadt(acpi_native_uint > > * > > ******************************************************************************/ > > > > -void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) > > +acpi_status > > +acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) > > { > > - > > + acpi_status status; > > /* > > * Check if the FADT is larger than the largest table that we expect > > * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue > > @@ -244,7 +248,9 @@ void acpi_tb_create_local_fadt(struct ac > > * 2) Validate some of the important values within the FADT > > */ > > acpi_tb_convert_fadt(); > > - acpi_tb_validate_fadt(); > > + status = acpi_tb_validate_fadt(); > > + > > + return_ACPI_STATUS(status); > > } > > > > /******************************************************************************* > > @@ -377,7 +383,7 @@ static void acpi_tb_convert_fadt(void) > > * > > * PARAMETERS: Table - Pointer to the FADT to be validated > > * > > - * RETURN: None > > + * RETURN: status > > * > > * DESCRIPTION: Validate various important fields within the FADT. If a problem > > * is found, issue a message, but no status is returned. > > @@ -391,12 +397,16 @@ static void acpi_tb_convert_fadt(void) > > * > > ******************************************************************************/ > > > > -static void acpi_tb_validate_fadt(void) > > +static acpi_status acpi_tb_validate_fadt(void) > > { > > u32 *address32; > > struct acpi_generic_address *address64; > > u8 length; > > acpi_native_uint i; > > + acpi_status status; > > + > > + /* The default status is AE_OK */ > > + status = AE_OK; > > > > /* Examine all of the 64-bit extended address fields (X fields) */ > > > > @@ -420,6 +430,12 @@ static void acpi_tb_validate_fadt(void) > > * Both the address and length must be non-zero. > > */ > > if (!address64->address || !length) { > > + /* > > + * Is it necessary to break the loop when the > > + * required filed has zero address or length? > > + * If it is required, please fix me. > > + */ > > + status = AE_ERROR; > > ACPI_ERROR((AE_INFO, > > "Required field \"%s\" has zero address and/or length: %8.8X%8.8X/%X", > > fadt_info_table[i].name, > > @@ -447,10 +463,18 @@ static void acpi_tb_validate_fadt(void) > > > > if (address64->address && *address32 && > > (address64->address != (u64) * address32)) { > > + /* > > + * Is it necessary to break the loop when the 32/64 > > + * address mismatches ? > > + * If it is required, please fix me. > > + */ > > + status = AE_ERROR; > > ACPI_ERROR((AE_INFO, > > "32/64X address mismatch in \"%s\": [%8.8X] [%8.8X%8.8X], using 64X", > > fadt_info_table[i].name, *address32, > > ACPI_FORMAT_UINT64(address64->address))); > > } > > } > > + > > + return_ACPI_STATUS(status); > > } > > > > > > -- > > To unsubscribe from this list: send the line "unsubscribe linux-acpi" in > > the body of a message to majordomo@vger.kernel.org > > More majordomo info at http://vger.kernel.org/majordomo-info.html > ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2008-04-22 0:54 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-04-18 10:41 [PATCH] ACPI : RSDT is forced to be used when 32/64X address mismatch in FADT Zhao Yakui 2008-04-18 11:29 ` Thomas Renninger 2008-04-18 13:35 ` Thomas Renninger 2008-04-19 4:24 ` Henrique de Moraes Holschuh 2008-04-21 10:07 ` Thomas Renninger 2008-04-21 14:39 ` Henrique de Moraes Holschuh 2008-04-22 8:46 ` Zhao Yakui
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox