Add a generic API for _OSC
PATCH 1/3 Add a generic API for _OSC
Add an API to execute _OSC. A lot of devices can have this method, so add a generic API.
--- drivers/acpi/bus.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 9 ++++++ 2 files changed, 81 insertions(+)
drivers/acpi/bus.c +72 -0
@@ -344,6 +344,78 @@ bool acpi_bus_can_wakeup(acpi_handle hanEXPORT_SYMBOL (acpi_bus_can_wakeup); +acpi_status acpi_run_osc (acpi_handle handle,struct acpi_osc_context *context) +{ +acpi_status status; +struct acpi_object_list input; +union acpi_object in_params[4 ]; +union acpi_object *out_obj; +u32 errors; + +if (!context) +return AE_ERROR ; + context->ret.length =ACPI_ALLOCATE_BUFFER ; + context->ret.pointer =NULL ; + +/* Setting up input parameters */ + input.count =4 ; + input.pointer = in_params; + in_params[0 ].type =ACPI_TYPE_BUFFER ; + in_params[0 ].buffer.length =16 ; + in_params[0 ].buffer.pointer = context->uuid; + in_params[1 ].type =ACPI_TYPE_INTEGER ; + in_params[1 ].integer.value = context->rev; + in_params[2 ].type =ACPI_TYPE_INTEGER ; + in_params[2 ].integer.value = context->cap.length/sizeof (u32); + in_params[3 ].type =ACPI_TYPE_BUFFER ; + in_params[3 ].buffer.length = context->cap.length; + in_params[3 ].buffer.pointer = context->cap.pointer; + + status =acpi_evaluate_object (handle,"_OSC" , &input, &context->ret); +if (ACPI_FAILURE (status)) +return status; + +/* return buffer should have the same length as cap buffer */ +if (context->ret.length != context->cap.length) +return AE_NULL_OBJECT ; + + out_obj = context->ret.pointer; +if (out_obj->type !=ACPI_TYPE_BUFFER ) { +printk (KERN_DEBUG "_OSC evaluation returned wrong type\n" ); + status =AE_TYPE ; + goto out_kfree; + } +/* Need to ignore the bit0 in result code */ + errors = *((u32 *)out_obj->buffer.pointer) & ~(1 <<0 ); +if (errors) { +if (errors &OSC_REQUEST_ERROR ) +printk (KERN_DEBUG "_OSC request failed\n" ); +if (errors &OSC_INVALID_UUID_ERROR ) +printk (KERN_DEBUG "_OSC invalid UUID\n" ); +if (errors &OSC_INVALID_REVISION_ERROR ) +printk (KERN_DEBUG "_OSC invalid revision\n" ); +if (errors &OSC_CAPABILITIES_MASK_ERROR ) { +if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE ] + &OSC_QUERY_ENABLE ) + goto out_success; +printk (KERN_DEBUG +"Firmware did not grant requested _OSC control\n" ); + status =AE_SUPPORT ; + goto out_kfree; + } + status =AE_ERROR ; + goto out_kfree; + } +out_success: +return AE_OK ; + +out_kfree: +kfree (context->ret.pointer); + context->ret.pointer =NULL ; +return status; +} +EXPORT_SYMBOL (acpi_run_osc); +/* -------------------------------------------------------------------------- Event Management -------------------------------------------------------------------------- */
include/linux/acpi.h +9 -0
@@ -253,6 +253,13 @@ void __init acpi_old_suspend_ordering(vovoid __init acpi_s4_no_nvs (void );#endif /* CONFIG_PM_SLEEP */ +struct acpi_osc_context { +u8 *uuid; +int rev; +struct acpi_buffer cap;/* arg2/arg3 */ +struct acpi_buffer ret;/* free by caller if success */ +}; +#define OSC_QUERY_TYPE 0#define OSC_SUPPORT_TYPE 1#define OSC_CONTROL_TYPE 2
@@ -265,6 +272,8 @@ void __init acpi_s4_no_nvs(void);#define OSC_INVALID_REVISION_ERROR 8#define OSC_CAPABILITIES_MASK_ERROR 16 +acpi_status acpi_run_osc (acpi_handle handle,struct acpi_osc_context *context); +/* _OSC DW1 Definition (OS Support Fields) */ #define OSC_EXT_PCI_CONFIG_SUPPORT 1#define OSC_ACTIVE_STATE_PWR_SUPPORT 2
Looks good.
Quoted 125 lines · Shaohua Li
Add an API to execute
_OSC. A lot of devices can have this method, so add a generic API.Signed-off-by Shaohua Li <[email protected]>--- drivers/acpi/bus.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 9 ++++++ 2 files changed, 81 insertions(+)Index:
linux/drivers/acpi/bus.c
===================================================================drivers/acpi/bus.c +72
-0@@ -344,6 +344,78 @@ bool acpi_bus_can_wakeup(acpi_handle hanEXPORT_SYMBOL (acpi_bus_can_wakeup); +acpi_status acpi_run_osc (acpi_handle handle,struct acpi_osc_context *context) +{ +acpi_status status; +struct acpi_object_list input; +union acpi_object in_params[4 ]; +union acpi_object *out_obj; +u32 errors; + +if (!context) +return AE_ERROR ; + context->ret.length =ACPI_ALLOCATE_BUFFER ; + context->ret.pointer =NULL ; + +/* Setting up input parameters */ + input.count =4 ; + input.pointer = in_params; + in_params[0 ].type =ACPI_TYPE_BUFFER ; + in_params[0 ].buffer.length =16 ; + in_params[0 ].buffer.pointer = context->uuid; + in_params[1 ].type =ACPI_TYPE_INTEGER ; + in_params[1 ].integer.value = context->rev; + in_params[2 ].type =ACPI_TYPE_INTEGER ; + in_params[2 ].integer.value = context->cap.length/sizeof (u32); + in_params[3 ].type =ACPI_TYPE_BUFFER ; + in_params[3 ].buffer.length = context->cap.length; + in_params[3 ].buffer.pointer = context->cap.pointer; + + status =acpi_evaluate_object (handle,"_OSC" , &input, &context->ret); +if (ACPI_FAILURE (status)) +return status; + +/* return buffer should have the same length as cap buffer */ +if (context->ret.length != context->cap.length) +return AE_NULL_OBJECT ; + + out_obj = context->ret.pointer; +if (out_obj->type !=ACPI_TYPE_BUFFER ) { +printk (KERN_DEBUG "_OSC evaluation returned wrong type\n" ); + status =AE_TYPE ; + goto out_kfree; + } +/* Need to ignore the bit0 in result code */ + errors = *((u32 *)out_obj->buffer.pointer) & ~(1 <<0 ); +if (errors) { +if (errors &OSC_REQUEST_ERROR ) +printk (KERN_DEBUG "_OSC request failed\n" ); +if (errors &OSC_INVALID_UUID_ERROR ) +printk (KERN_DEBUG "_OSC invalid UUID\n" ); +if (errors &OSC_INVALID_REVISION_ERROR ) +printk (KERN_DEBUG "_OSC invalid revision\n" ); +if (errors &OSC_CAPABILITIES_MASK_ERROR ) { +if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE ] + &OSC_QUERY_ENABLE ) + goto out_success; +printk (KERN_DEBUG +"Firmware did not grant requested _OSC control\n" ); + status =AE_SUPPORT ; + goto out_kfree; + } + status =AE_ERROR ; + goto out_kfree; + } +out_success: +return AE_OK ; + +out_kfree: +kfree (context->ret.pointer); + context->ret.pointer =NULL ; +return status; +} +EXPORT_SYMBOL (acpi_run_osc); +/* -------------------------------------------------------------------------- Event Management -------------------------------------------------------------------------- */ Index:
linux/include/linux/acpi.h
===================================================================include/linux/acpi.h +9
-1@@ -253,6 +253,13 @@ void __init acpi_old_suspend_ordering(vovoid __init acpi_s4_no_nvs (void );#endif /* CONFIG_PM_SLEEP */ +struct acpi_osc_context { +u8 *uuid; +int rev; +struct acpi_buffer cap;/* arg2/arg3 */ +struct acpi_buffer ret;/* free by caller if success */ +}; +#define OSC_QUERY_TYPE 0#define OSC_SUPPORT_TYPE 1#define OSC_CONTROL_TYPE 2@@ -265,6 +272,8 @@ void __init acpi_s4_no_nvs(void);#define OSC_INVALID_REVISION_ERROR 8#define OSC_CAPABILITIES_MASK_ERROR 16 +acpi_status acpi_run_osc (acpi_handle handle,struct acpi_osc_context *context); +/* _OSC DW1 Definition (OS Support Fields) */ #define OSC_EXT_PCI_CONFIG_SUPPORT 1#define OSC_ACTIVE_STATE_PWR_SUPPORT 2 --To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 14 lines · Shaohua Li
Add an API to execute
_OSC. A lot of devices can have this method, so add a generic API.drivers/acpi/bus.c +11
-0+ out_obj = context->ret.pointer; +if (out_obj->type !=ACPI_TYPE_BUFFER ) { +printk (KERN_DEBUG "_OSC evaluation returned wrong type\n" ); + status =AE_TYPE ; + goto out_kfree; + } +/* Need to ignore the bit0 in result code */ + errors = *((u32 *)out_obj->buffer.pointer) & ~(1 <<0 ); +if (errors) { +if (errors &OSC_REQUEST_ERROR ) +printk (KERN_DEBUG "_OSC request failed\n" );
drivers/acpi/bus.c bool acpi_bus_can_wakeup(acpi_handle han · line 402
Quoted 10 lines
drivers/acpi/bus.c +10
-0+if (errors &OSC_INVALID_UUID_ERROR ) +printk (KERN_DEBUG "_OSC invalid UUID\n" ); +if (errors &OSC_INVALID_REVISION_ERROR ) +printk (KERN_DEBUG "_OSC invalid revision\n" ); +if (errors &OSC_CAPABILITIES_MASK_ERROR ) { +if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE ] + &OSC_QUERY_ENABLE ) + goto out_success; +printk (KERN_DEBUG +"Firmware did not grant requested _OSC control\n" );
On all these printks, it would be very useful to have some indication of what the OS requested and which specific _OSC method we executed, e.g., an ACPI device name or a namespace path.
Bjorn
Quoted 21 lines · Bjorn Helgaas
Quoted 20 lines · Shaohua Li
Add an API to execute
_OSC. A lot of devices can have this method, so add a generic API.drivers/acpi/bus.c +17
-0+ out_obj = context->ret.pointer; +if (out_obj->type !=ACPI_TYPE_BUFFER ) { +printk (KERN_DEBUG "_OSC evaluation returned wrong type\n" ); + status =AE_TYPE ; + goto out_kfree; + } +/* Need to ignore the bit0 in result code */ + errors = *((u32 *)out_obj->buffer.pointer) & ~(1 <<0 ); +if (errors) { +if (errors &OSC_REQUEST_ERROR ) +printk (KERN_DEBUG "_OSC request failed\n" ); +if (errors &OSC_INVALID_UUID_ERROR ) +printk (KERN_DEBUG "_OSC invalid UUID\n" ); +if (errors &OSC_INVALID_REVISION_ERROR ) +printk (KERN_DEBUG "_OSC invalid revision\n" ); +if (errors &OSC_CAPABILITIES_MASK_ERROR ) { + if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE]
Quoted 9 lines
drivers/acpi/bus.c bool acpi_bus_can_wakeup(acpi_handle han · line 402
Quoted 4 lines
drivers/acpi/bus.c +4
-0+ & OSC_QUERY_ENABLE) + goto out_success; +printk (KERN_DEBUG +"Firmware did not grant requested _OSC control\n" );On all these printks, it would be very useful to have some indication of what the OS requested and which specific
_OSCmethod we executed, e.g., an ACPI device name or a namespace path.
I think the following printk is confusing and should be removed.
Quoted 2 lines
drivers/acpi/bus.c bool acpi_bus_can_wakeup(acpi_handle han · line 402
Quoted 2 lines
drivers/acpi/bus.c +2
-0+printk (KERN_DEBUG +"Firmware did not grant requested _OSC control\n" );
People might think something wrong is happening on OS or firmware. Actually I had been asked about this message several times.
Thanks,
Kenji Kaneshige
Hi Shaohua,
Could you also make it take a spec string as argument, not a prepared byte buffer?
Regards,
Alex.
Shaohua Li пишет:
Quoted 120 lines
Add an API to execute
_OSC. A lot of devices can have this method, so add a generic API.Signed-off-by Shaohua Li <[email protected]>--- drivers/acpi/bus.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 9 ++++++ 2 files changed, 81 insertions(+)Index:
linux/drivers/acpi/bus.c
===================================================================drivers/acpi/bus.c +72
-0@@ -344,6 +344,78 @@ bool acpi_bus_can_wakeup(acpi_handle hanEXPORT_SYMBOL (acpi_bus_can_wakeup); +acpi_status acpi_run_osc (acpi_handle handle,struct acpi_osc_context *context) +{ +acpi_status status; +struct acpi_object_list input; +union acpi_object in_params[4 ]; +union acpi_object *out_obj; +u32 errors; + +if (!context) +return AE_ERROR ; + context->ret.length =ACPI_ALLOCATE_BUFFER ; + context->ret.pointer =NULL ; + +/* Setting up input parameters */ + input.count =4 ; + input.pointer = in_params; + in_params[0 ].type =ACPI_TYPE_BUFFER ; + in_params[0 ].buffer.length =16 ; + in_params[0 ].buffer.pointer = context->uuid; + in_params[1 ].type =ACPI_TYPE_INTEGER ; + in_params[1 ].integer.value = context->rev; + in_params[2 ].type =ACPI_TYPE_INTEGER ; + in_params[2 ].integer.value = context->cap.length/sizeof (u32); + in_params[3 ].type =ACPI_TYPE_BUFFER ; + in_params[3 ].buffer.length = context->cap.length; + in_params[3 ].buffer.pointer = context->cap.pointer; + + status =acpi_evaluate_object (handle,"_OSC" , &input, &context->ret); +if (ACPI_FAILURE (status)) +return status; + +/* return buffer should have the same length as cap buffer */ +if (context->ret.length != context->cap.length) +return AE_NULL_OBJECT ; + + out_obj = context->ret.pointer; +if (out_obj->type !=ACPI_TYPE_BUFFER ) { +printk (KERN_DEBUG "_OSC evaluation returned wrong type\n" ); + status =AE_TYPE ; + goto out_kfree; + } +/* Need to ignore the bit0 in result code */ + errors = *((u32 *)out_obj->buffer.pointer) & ~(1 <<0 ); +if (errors) { +if (errors &OSC_REQUEST_ERROR ) +printk (KERN_DEBUG "_OSC request failed\n" ); +if (errors &OSC_INVALID_UUID_ERROR ) +printk (KERN_DEBUG "_OSC invalid UUID\n" ); +if (errors &OSC_INVALID_REVISION_ERROR ) +printk (KERN_DEBUG "_OSC invalid revision\n" ); +if (errors &OSC_CAPABILITIES_MASK_ERROR ) { +if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE ] + &OSC_QUERY_ENABLE ) + goto out_success; +printk (KERN_DEBUG +"Firmware did not grant requested _OSC control\n" ); + status =AE_SUPPORT ; + goto out_kfree; + } + status =AE_ERROR ; + goto out_kfree; + } +out_success: +return AE_OK ; + +out_kfree: +kfree (context->ret.pointer); + context->ret.pointer =NULL ; +return status; +} +EXPORT_SYMBOL (acpi_run_osc); +/* -------------------------------------------------------------------------- Event Management -------------------------------------------------------------------------- */ Index:
linux/include/linux/acpi.h
===================================================================include/linux/acpi.h +9
-1@@ -253,6 +253,13 @@ void __init acpi_old_suspend_ordering(vovoid __init acpi_s4_no_nvs (void );#endif /* CONFIG_PM_SLEEP */ +struct acpi_osc_context { +u8 *uuid; +int rev; +struct acpi_buffer cap;/* arg2/arg3 */ +struct acpi_buffer ret;/* free by caller if success */ +}; +#define OSC_QUERY_TYPE 0#define OSC_SUPPORT_TYPE 1#define OSC_CONTROL_TYPE 2@@ -265,6 +272,8 @@ void __init acpi_s4_no_nvs(void);#define OSC_INVALID_REVISION_ERROR 8#define OSC_CAPABILITIES_MASK_ERROR 16 +acpi_status acpi_run_osc (acpi_handle handle,struct acpi_osc_context *context); +/* _OSC DW1 Definition (OS Support Fields) */ #define OSC_EXT_PCI_CONFIG_SUPPORT 1#define OSC_ACTIVE_STATE_PWR_SUPPORT 2 --
Quoted 4 lines
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected]
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 4 lines · Alexey Starikovskiy
Hi Shaohua,
Could you also make it take a spec string as argument, not a prepared byte buffer?
Hi,
did you mean take the uuid string as an argument of the API? We can add a function to convert a uuid string to binary, but I didn't see any benefit to take the string as argument.
Thanks,
Shaohua
Shaohua Li пишет:
Quoted 7 lines · Alexey Starikovskiy
Quoted 6 lines
Hi Shaohua,
Could you also make it take a spec string as argument, not a prepared byte buffer?
Quoted 8 lines
Hi,
did you mean take the uuid string as an argument of the API? We can add a function to convert a uuid string to binary, but I didn't see any benefit to take the string as argument.Thanks,
Shaohua
Hi,
Well, right now you are programming in machine codes. If you make mistake, no one will notice, even yourself.
Programming languages were invented to make programs look more readable by humans, so that they can see mistakes more easily.
For the same reason ACPI specification declares UUIDs as strings, while having them in AML as byte arrays.
Function to convert UUID to byte array already exists, you just need to use it...
Regards,
Alex.
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 16 lines · Alexey Starikovskiy
Shaohua Li пишет:
Quoted 7 lines · Alexey Starikovskiy
Quoted 6 lines
Hi Shaohua,
Could you also make it take a spec string as argument, not a prepared byte buffer?
Quoted 8 lines
Hi,
did you mean take the uuid string as an argument of the API? We can add a function to convert a uuid string to binary, but I didn't see any benefit to take the string as argument.Thanks,
Shaohua
Quoted 9 lines
Hi,
Well, right now you are programming in machine codes. If you make mistake, no one will notice, even yourself.
Programming languages were invented to make programs look more readable by humans, so that they can see mistakes more easily.
For the same reason ACPI specification declares UUIDs as strings, while having them in AML as byte arrays.
Function to convert UUID to byte array already exists, you just need to use it...
frankly even you use UUID string, it's easy to make mistakes. The string is too long. BTW, which function can convert UUID to byte array?
Thanks,
Shaohua
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Shaohua Li пишет:
Quoted 32 lines · Alexey Starikovskiy
Quoted 21 lines
Shaohua Li пишет:
Quoted 9 lines · Alexey Starikovskiy
Quoted 8 lines
Hi Shaohua,
Could you also make it take a spec string as argument, not a prepared byte buffer?
Quoted 9 lines
Hi,
did you mean take the uuid string as an argument of the API? We can add a function to convert a uuid string to binary, but I didn't see any benefit to take the string as argument.Thanks,
ShaohuaQuoted 10 lines
Hi,
Well, right now you are programming in machine codes. If you make mistake, no one will notice, even yourself.
Programming languages were invented to make programs look more readable by humans, so that they can see mistakes more easily.
For the same reason ACPI specification declares UUIDs as strings, while having them in AML as byte arrays.
Function to convert UUID to byte array already exists, you just need to use it...
Quoted 2 lines
frankly even you use UUID string, it's easy to make mistakes. The string is too long.
Copy-paste is already invented too :)
Quoted 2 lines
BTW, which function can convert UUID to byte array?
aslopcodes.c:633 OpcDoUuId().
Regards,
Alex.
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html