2019-05-27 09:55:06 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2014-04-04 22:15:42 +04:00
/*
* Alienware AlienFX control
*
* Copyright ( C ) 2014 Dell Inc < mario_limonciello @ dell . com >
*/
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
# include <linux/acpi.h>
# include <linux/module.h>
# include <linux/platform_device.h>
# include <linux/dmi.h>
# include <linux/leds.h>
# define LEGACY_CONTROL_GUID "A90597CE-A997-11DA-B012-B622A1EF5492"
# define LEGACY_POWER_CONTROL_GUID "A80593CE-A997-11DA-B012-B622A1EF5492"
# define WMAX_CONTROL_GUID "A70591CE-A997-11DA-B012-B622A1EF5492"
# define WMAX_METHOD_HDMI_SOURCE 0x1
# define WMAX_METHOD_HDMI_STATUS 0x2
# define WMAX_METHOD_BRIGHTNESS 0x3
# define WMAX_METHOD_ZONE_CONTROL 0x4
2014-05-08 00:08:10 +04:00
# define WMAX_METHOD_HDMI_CABLE 0x5
2016-02-03 00:38:54 +03:00
# define WMAX_METHOD_AMPLIFIER_CABLE 0x6
2016-02-03 00:38:55 +03:00
# define WMAX_METHOD_DEEP_SLEEP_CONTROL 0x0B
# define WMAX_METHOD_DEEP_SLEEP_STATUS 0x0C
2014-04-04 22:15:42 +04:00
MODULE_AUTHOR ( " Mario Limonciello <mario_limonciello@dell.com> " ) ;
MODULE_DESCRIPTION ( " Alienware special feature control " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_ALIAS ( " wmi: " LEGACY_CONTROL_GUID ) ;
MODULE_ALIAS ( " wmi: " WMAX_CONTROL_GUID ) ;
enum INTERFACE_FLAGS {
LEGACY ,
WMAX ,
} ;
enum LEGACY_CONTROL_STATES {
LEGACY_RUNNING = 1 ,
LEGACY_BOOTING = 0 ,
LEGACY_SUSPEND = 3 ,
} ;
enum WMAX_CONTROL_STATES {
WMAX_RUNNING = 0xFF ,
WMAX_BOOTING = 0 ,
WMAX_SUSPEND = 3 ,
} ;
struct quirk_entry {
u8 num_zones ;
2014-07-24 08:19:23 +04:00
u8 hdmi_mux ;
2016-02-03 00:38:54 +03:00
u8 amplifier ;
2016-02-03 00:38:55 +03:00
u8 deepslp ;
2014-04-04 22:15:42 +04:00
} ;
static struct quirk_entry * quirks ;
2017-11-16 05:35:07 +03:00
static struct quirk_entry quirk_inspiron5675 = {
. num_zones = 2 ,
. hdmi_mux = 0 ,
. amplifier = 0 ,
. deepslp = 0 ,
} ;
2014-04-04 22:15:42 +04:00
static struct quirk_entry quirk_unknown = {
. num_zones = 2 ,
2014-07-24 08:19:23 +04:00
. hdmi_mux = 0 ,
2016-02-03 00:38:54 +03:00
. amplifier = 0 ,
2016-02-03 00:38:55 +03:00
. deepslp = 0 ,
2014-04-04 22:15:42 +04:00
} ;
2016-02-03 00:38:53 +03:00
static struct quirk_entry quirk_x51_r1_r2 = {
2014-04-04 22:15:42 +04:00
. num_zones = 3 ,
2016-02-03 00:38:54 +03:00
. hdmi_mux = 0 ,
. amplifier = 0 ,
2016-02-03 00:38:55 +03:00
. deepslp = 0 ,
2014-07-24 08:19:23 +04:00
} ;
2016-02-03 00:38:53 +03:00
static struct quirk_entry quirk_x51_r3 = {
. num_zones = 4 ,
. hdmi_mux = 0 ,
2016-02-03 00:38:54 +03:00
. amplifier = 1 ,
2016-02-03 00:38:55 +03:00
. deepslp = 0 ,
2016-02-03 00:38:53 +03:00
} ;
2014-07-24 08:19:23 +04:00
static struct quirk_entry quirk_asm100 = {
. num_zones = 2 ,
. hdmi_mux = 1 ,
2016-02-03 00:38:54 +03:00
. amplifier = 0 ,
2016-02-03 00:38:55 +03:00
. deepslp = 0 ,
2014-04-04 22:15:42 +04:00
} ;
2016-02-03 00:38:56 +03:00
static struct quirk_entry quirk_asm200 = {
. num_zones = 2 ,
. hdmi_mux = 1 ,
. amplifier = 0 ,
. deepslp = 1 ,
} ;
static struct quirk_entry quirk_asm201 = {
. num_zones = 2 ,
. hdmi_mux = 1 ,
. amplifier = 1 ,
. deepslp = 1 ,
} ;
2014-07-16 21:43:07 +04:00
static int __init dmi_matched ( const struct dmi_system_id * dmi )
2014-04-04 22:15:42 +04:00
{
quirks = dmi - > driver_data ;
return 1 ;
}
2014-07-16 21:43:07 +04:00
static const struct dmi_system_id alienware_quirks [ ] __initconst = {
2014-04-04 22:15:42 +04:00
{
. callback = dmi_matched ,
2016-02-03 00:38:53 +03:00
. ident = " Alienware X51 R3 " ,
2014-04-04 22:15:42 +04:00
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Alienware " ) ,
2016-02-03 00:38:53 +03:00
DMI_MATCH ( DMI_PRODUCT_NAME , " Alienware X51 R3 " ) ,
2014-04-04 22:15:42 +04:00
} ,
2016-02-03 00:38:53 +03:00
. driver_data = & quirk_x51_r3 ,
2014-04-04 22:15:42 +04:00
} ,
{
. callback = dmi_matched ,
. ident = " Alienware X51 R2 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Alienware " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Alienware X51 R2 " ) ,
} ,
2016-02-03 00:38:53 +03:00
. driver_data = & quirk_x51_r1_r2 ,
} ,
{
. callback = dmi_matched ,
. ident = " Alienware X51 R1 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Alienware " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Alienware X51 " ) ,
} ,
. driver_data = & quirk_x51_r1_r2 ,
2014-04-04 22:15:42 +04:00
} ,
2014-07-24 08:19:23 +04:00
{
2016-02-03 00:38:52 +03:00
. callback = dmi_matched ,
. ident = " Alienware ASM100 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Alienware " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " ASM100 " ) ,
} ,
. driver_data = & quirk_asm100 ,
} ,
2016-02-03 00:38:56 +03:00
{
. callback = dmi_matched ,
. ident = " Alienware ASM200 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Alienware " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " ASM200 " ) ,
} ,
. driver_data = & quirk_asm200 ,
} ,
{
. callback = dmi_matched ,
. ident = " Alienware ASM201 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Alienware " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " ASM201 " ) ,
} ,
. driver_data = & quirk_asm201 ,
} ,
2017-11-16 05:35:07 +03:00
{
. callback = dmi_matched ,
. ident = " Dell Inc. Inspiron 5675 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Dell Inc. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Inspiron 5675 " ) ,
} ,
. driver_data = & quirk_inspiron5675 ,
} ,
2014-04-04 22:15:42 +04:00
{ }
} ;
struct color_platform {
u8 blue ;
u8 green ;
u8 red ;
} __packed ;
struct platform_zone {
u8 location ;
struct device_attribute * attr ;
struct color_platform colors ;
} ;
struct wmax_brightness_args {
u32 led_mask ;
u32 percentage ;
} ;
2016-02-03 00:38:54 +03:00
struct wmax_basic_args {
2014-04-04 22:15:42 +04:00
u8 arg ;
} ;
struct legacy_led_args {
struct color_platform colors ;
u8 brightness ;
u8 state ;
} __packed ;
struct wmax_led_args {
u32 led_mask ;
struct color_platform colors ;
u8 state ;
} __packed ;
static struct platform_device * platform_device ;
static struct device_attribute * zone_dev_attrs ;
static struct attribute * * zone_attrs ;
static struct platform_zone * zone_data ;
static struct platform_driver platform_driver = {
. driver = {
. name = " alienware-wmi " ,
}
} ;
static struct attribute_group zone_attribute_group = {
. name = " rgb_zones " ,
} ;
static u8 interface ;
static u8 lighting_control_state ;
static u8 global_brightness ;
/*
* Helpers used for zone control
2016-02-03 00:38:57 +03:00
*/
2014-04-04 22:15:42 +04:00
static int parse_rgb ( const char * buf , struct platform_zone * zone )
{
long unsigned int rgb ;
int ret ;
union color_union {
struct color_platform cp ;
int package ;
} repackager ;
ret = kstrtoul ( buf , 16 , & rgb ) ;
if ( ret )
return ret ;
/* RGB triplet notation is 24-bit hexadecimal */
if ( rgb > 0xFFFFFF )
return - EINVAL ;
repackager . package = rgb & 0x0f0f0f0f ;
pr_debug ( " alienware-wmi: r: %d g:%d b: %d \n " ,
repackager . cp . red , repackager . cp . green , repackager . cp . blue ) ;
zone - > colors = repackager . cp ;
return 0 ;
}
static struct platform_zone * match_zone ( struct device_attribute * attr )
{
platform/x86: alienware-wmi: fix format string overflow warning
gcc points out a possible format string overflow for a large value of 'zone':
drivers/platform/x86/alienware-wmi.c: In function 'alienware_wmi_init':
drivers/platform/x86/alienware-wmi.c:461:24: error: '%02X' directive writing between 2 and 8 bytes into a region of size 6 [-Werror=format-overflow=]
sprintf(buffer, "zone%02X", i);
^~~~
drivers/platform/x86/alienware-wmi.c:461:19: note: directive argument in the range [0, 2147483646]
sprintf(buffer, "zone%02X", i);
^~~~~~~~~~
drivers/platform/x86/alienware-wmi.c:461:3: note: 'sprintf' output between 7 and 13 bytes into a destination of size 10
This replaces the 'int' variable with an 'u8' to make sure
it always fits, renaming the variable to 'zone' for clarity.
Unfortunately, gcc-7.1.1 still warns about it with that change, which
seems to be unintended by the gcc developers. I have opened a bug
against gcc with a reduced test case. As a workaround, I also
change the format string to use "%02hhX", which shuts up the
warning in that version.
Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81483
Link: https://patchwork.ozlabs.org/patch/788415/
Suggested-by: Andy Shevchenko <andy@infradead.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
[andy: added empty lines after u8 zone; definitions]
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
2017-07-20 19:00:51 +03:00
u8 zone ;
for ( zone = 0 ; zone < quirks - > num_zones ; zone + + ) {
if ( ( struct device_attribute * ) zone_data [ zone ] . attr = = attr ) {
2014-04-04 22:15:42 +04:00
pr_debug ( " alienware-wmi: matched zone location: %d \n " ,
platform/x86: alienware-wmi: fix format string overflow warning
gcc points out a possible format string overflow for a large value of 'zone':
drivers/platform/x86/alienware-wmi.c: In function 'alienware_wmi_init':
drivers/platform/x86/alienware-wmi.c:461:24: error: '%02X' directive writing between 2 and 8 bytes into a region of size 6 [-Werror=format-overflow=]
sprintf(buffer, "zone%02X", i);
^~~~
drivers/platform/x86/alienware-wmi.c:461:19: note: directive argument in the range [0, 2147483646]
sprintf(buffer, "zone%02X", i);
^~~~~~~~~~
drivers/platform/x86/alienware-wmi.c:461:3: note: 'sprintf' output between 7 and 13 bytes into a destination of size 10
This replaces the 'int' variable with an 'u8' to make sure
it always fits, renaming the variable to 'zone' for clarity.
Unfortunately, gcc-7.1.1 still warns about it with that change, which
seems to be unintended by the gcc developers. I have opened a bug
against gcc with a reduced test case. As a workaround, I also
change the format string to use "%02hhX", which shuts up the
warning in that version.
Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81483
Link: https://patchwork.ozlabs.org/patch/788415/
Suggested-by: Andy Shevchenko <andy@infradead.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
[andy: added empty lines after u8 zone; definitions]
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
2017-07-20 19:00:51 +03:00
zone_data [ zone ] . location ) ;
return & zone_data [ zone ] ;
2014-04-04 22:15:42 +04:00
}
}
return NULL ;
}
/*
* Individual RGB zone control
2016-02-03 00:38:57 +03:00
*/
2014-04-04 22:15:42 +04:00
static int alienware_update_led ( struct platform_zone * zone )
{
int method_id ;
acpi_status status ;
char * guid ;
struct acpi_buffer input ;
struct legacy_led_args legacy_args ;
2016-02-03 00:38:54 +03:00
struct wmax_led_args wmax_basic_args ;
2014-04-04 22:15:42 +04:00
if ( interface = = WMAX ) {
2016-02-03 00:38:54 +03:00
wmax_basic_args . led_mask = 1 < < zone - > location ;
wmax_basic_args . colors = zone - > colors ;
wmax_basic_args . state = lighting_control_state ;
2014-04-04 22:15:42 +04:00
guid = WMAX_CONTROL_GUID ;
method_id = WMAX_METHOD_ZONE_CONTROL ;
2016-02-03 00:38:54 +03:00
input . length = ( acpi_size ) sizeof ( wmax_basic_args ) ;
input . pointer = & wmax_basic_args ;
2014-04-04 22:15:42 +04:00
} else {
legacy_args . colors = zone - > colors ;
legacy_args . brightness = global_brightness ;
legacy_args . state = 0 ;
if ( lighting_control_state = = LEGACY_BOOTING | |
lighting_control_state = = LEGACY_SUSPEND ) {
guid = LEGACY_POWER_CONTROL_GUID ;
legacy_args . state = lighting_control_state ;
} else
guid = LEGACY_CONTROL_GUID ;
method_id = zone - > location + 1 ;
input . length = ( acpi_size ) sizeof ( legacy_args ) ;
input . pointer = & legacy_args ;
}
pr_debug ( " alienware-wmi: guid %s method %d \n " , guid , method_id ) ;
2017-06-22 01:01:35 +03:00
status = wmi_evaluate_method ( guid , 0 , method_id , & input , NULL ) ;
2014-04-04 22:15:42 +04:00
if ( ACPI_FAILURE ( status ) )
pr_err ( " alienware-wmi: zone set failure: %u \n " , status ) ;
return ACPI_FAILURE ( status ) ;
}
static ssize_t zone_show ( struct device * dev , struct device_attribute * attr ,
char * buf )
{
struct platform_zone * target_zone ;
target_zone = match_zone ( attr ) ;
if ( target_zone = = NULL )
return sprintf ( buf , " red: -1, green: -1, blue: -1 \n " ) ;
return sprintf ( buf , " red: %d, green: %d, blue: %d \n " ,
target_zone - > colors . red ,
target_zone - > colors . green , target_zone - > colors . blue ) ;
}
static ssize_t zone_set ( struct device * dev , struct device_attribute * attr ,
const char * buf , size_t count )
{
struct platform_zone * target_zone ;
int ret ;
target_zone = match_zone ( attr ) ;
if ( target_zone = = NULL ) {
pr_err ( " alienware-wmi: invalid target zone \n " ) ;
return 1 ;
}
ret = parse_rgb ( buf , target_zone ) ;
if ( ret )
return ret ;
ret = alienware_update_led ( target_zone ) ;
return ret ? ret : count ;
}
/*
* LED Brightness ( Global )
2016-02-03 00:38:57 +03:00
*/
2014-04-04 22:15:42 +04:00
static int wmax_brightness ( int brightness )
{
acpi_status status ;
struct acpi_buffer input ;
struct wmax_brightness_args args = {
. led_mask = 0xFF ,
. percentage = brightness ,
} ;
input . length = ( acpi_size ) sizeof ( args ) ;
input . pointer = & args ;
2017-06-22 01:01:35 +03:00
status = wmi_evaluate_method ( WMAX_CONTROL_GUID , 0 ,
2014-04-04 22:15:42 +04:00
WMAX_METHOD_BRIGHTNESS , & input , NULL ) ;
if ( ACPI_FAILURE ( status ) )
pr_err ( " alienware-wmi: brightness set failure: %u \n " , status ) ;
return ACPI_FAILURE ( status ) ;
}
static void global_led_set ( struct led_classdev * led_cdev ,
enum led_brightness brightness )
{
int ret ;
global_brightness = brightness ;
if ( interface = = WMAX )
ret = wmax_brightness ( brightness ) ;
else
ret = alienware_update_led ( & zone_data [ 0 ] ) ;
if ( ret )
pr_err ( " LED brightness update failed \n " ) ;
}
static enum led_brightness global_led_get ( struct led_classdev * led_cdev )
{
return global_brightness ;
}
static struct led_classdev global_led = {
. brightness_set = global_led_set ,
. brightness_get = global_led_get ,
. name = " alienware::global_brightness " ,
} ;
/*
* Lighting control state device attribute ( Global )
2016-02-03 00:38:57 +03:00
*/
2014-04-04 22:15:42 +04:00
static ssize_t show_control_state ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
if ( lighting_control_state = = LEGACY_BOOTING )
return scnprintf ( buf , PAGE_SIZE , " [booting] running suspend \n " ) ;
else if ( lighting_control_state = = LEGACY_SUSPEND )
return scnprintf ( buf , PAGE_SIZE , " booting running [suspend] \n " ) ;
return scnprintf ( buf , PAGE_SIZE , " booting [running] suspend \n " ) ;
}
static ssize_t store_control_state ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
{
long unsigned int val ;
if ( strcmp ( buf , " booting \n " ) = = 0 )
val = LEGACY_BOOTING ;
else if ( strcmp ( buf , " suspend \n " ) = = 0 )
val = LEGACY_SUSPEND ;
else if ( interface = = LEGACY )
val = LEGACY_RUNNING ;
else
val = WMAX_RUNNING ;
lighting_control_state = val ;
pr_debug ( " alienware-wmi: updated control state to %d \n " ,
lighting_control_state ) ;
return count ;
}
static DEVICE_ATTR ( lighting_control_state , 0644 , show_control_state ,
store_control_state ) ;
static int alienware_zone_init ( struct platform_device * dev )
{
platform/x86: alienware-wmi: fix format string overflow warning
gcc points out a possible format string overflow for a large value of 'zone':
drivers/platform/x86/alienware-wmi.c: In function 'alienware_wmi_init':
drivers/platform/x86/alienware-wmi.c:461:24: error: '%02X' directive writing between 2 and 8 bytes into a region of size 6 [-Werror=format-overflow=]
sprintf(buffer, "zone%02X", i);
^~~~
drivers/platform/x86/alienware-wmi.c:461:19: note: directive argument in the range [0, 2147483646]
sprintf(buffer, "zone%02X", i);
^~~~~~~~~~
drivers/platform/x86/alienware-wmi.c:461:3: note: 'sprintf' output between 7 and 13 bytes into a destination of size 10
This replaces the 'int' variable with an 'u8' to make sure
it always fits, renaming the variable to 'zone' for clarity.
Unfortunately, gcc-7.1.1 still warns about it with that change, which
seems to be unintended by the gcc developers. I have opened a bug
against gcc with a reduced test case. As a workaround, I also
change the format string to use "%02hhX", which shuts up the
warning in that version.
Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81483
Link: https://patchwork.ozlabs.org/patch/788415/
Suggested-by: Andy Shevchenko <andy@infradead.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
[andy: added empty lines after u8 zone; definitions]
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
2017-07-20 19:00:51 +03:00
u8 zone ;
2014-04-04 22:15:42 +04:00
char buffer [ 10 ] ;
char * name ;
if ( interface = = WMAX ) {
lighting_control_state = WMAX_RUNNING ;
} else if ( interface = = LEGACY ) {
lighting_control_state = LEGACY_RUNNING ;
}
2014-05-08 00:08:09 +04:00
global_led . max_brightness = 0x0F ;
2014-04-04 22:15:42 +04:00
global_brightness = global_led . max_brightness ;
/*
* - zone_dev_attrs num_zones + 1 is for individual zones and then
* null terminated
* - zone_attrs num_zones + 2 is for all attrs in zone_dev_attrs +
* the lighting control + null terminated
* - zone_data num_zones is for the distinct zones
*/
zone_dev_attrs =
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:03:40 +03:00
kcalloc ( quirks - > num_zones + 1 , sizeof ( struct device_attribute ) ,
2014-04-04 22:15:42 +04:00
GFP_KERNEL ) ;
2014-04-04 23:40:20 +04:00
if ( ! zone_dev_attrs )
return - ENOMEM ;
2014-04-04 22:15:42 +04:00
zone_attrs =
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:03:40 +03:00
kcalloc ( quirks - > num_zones + 2 , sizeof ( struct attribute * ) ,
2014-04-04 22:15:42 +04:00
GFP_KERNEL ) ;
2014-04-04 23:40:20 +04:00
if ( ! zone_attrs )
return - ENOMEM ;
2014-04-04 22:15:42 +04:00
zone_data =
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:03:40 +03:00
kcalloc ( quirks - > num_zones , sizeof ( struct platform_zone ) ,
2014-04-04 22:15:42 +04:00
GFP_KERNEL ) ;
2014-04-04 23:40:20 +04:00
if ( ! zone_data )
return - ENOMEM ;
2014-04-04 22:15:42 +04:00
platform/x86: alienware-wmi: fix format string overflow warning
gcc points out a possible format string overflow for a large value of 'zone':
drivers/platform/x86/alienware-wmi.c: In function 'alienware_wmi_init':
drivers/platform/x86/alienware-wmi.c:461:24: error: '%02X' directive writing between 2 and 8 bytes into a region of size 6 [-Werror=format-overflow=]
sprintf(buffer, "zone%02X", i);
^~~~
drivers/platform/x86/alienware-wmi.c:461:19: note: directive argument in the range [0, 2147483646]
sprintf(buffer, "zone%02X", i);
^~~~~~~~~~
drivers/platform/x86/alienware-wmi.c:461:3: note: 'sprintf' output between 7 and 13 bytes into a destination of size 10
This replaces the 'int' variable with an 'u8' to make sure
it always fits, renaming the variable to 'zone' for clarity.
Unfortunately, gcc-7.1.1 still warns about it with that change, which
seems to be unintended by the gcc developers. I have opened a bug
against gcc with a reduced test case. As a workaround, I also
change the format string to use "%02hhX", which shuts up the
warning in that version.
Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81483
Link: https://patchwork.ozlabs.org/patch/788415/
Suggested-by: Andy Shevchenko <andy@infradead.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
[andy: added empty lines after u8 zone; definitions]
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
2017-07-20 19:00:51 +03:00
for ( zone = 0 ; zone < quirks - > num_zones ; zone + + ) {
sprintf ( buffer , " zone%02hhX " , zone ) ;
2014-04-04 22:15:42 +04:00
name = kstrdup ( buffer , GFP_KERNEL ) ;
if ( name = = NULL )
return 1 ;
platform/x86: alienware-wmi: fix format string overflow warning
gcc points out a possible format string overflow for a large value of 'zone':
drivers/platform/x86/alienware-wmi.c: In function 'alienware_wmi_init':
drivers/platform/x86/alienware-wmi.c:461:24: error: '%02X' directive writing between 2 and 8 bytes into a region of size 6 [-Werror=format-overflow=]
sprintf(buffer, "zone%02X", i);
^~~~
drivers/platform/x86/alienware-wmi.c:461:19: note: directive argument in the range [0, 2147483646]
sprintf(buffer, "zone%02X", i);
^~~~~~~~~~
drivers/platform/x86/alienware-wmi.c:461:3: note: 'sprintf' output between 7 and 13 bytes into a destination of size 10
This replaces the 'int' variable with an 'u8' to make sure
it always fits, renaming the variable to 'zone' for clarity.
Unfortunately, gcc-7.1.1 still warns about it with that change, which
seems to be unintended by the gcc developers. I have opened a bug
against gcc with a reduced test case. As a workaround, I also
change the format string to use "%02hhX", which shuts up the
warning in that version.
Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81483
Link: https://patchwork.ozlabs.org/patch/788415/
Suggested-by: Andy Shevchenko <andy@infradead.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
[andy: added empty lines after u8 zone; definitions]
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
2017-07-20 19:00:51 +03:00
sysfs_attr_init ( & zone_dev_attrs [ zone ] . attr ) ;
zone_dev_attrs [ zone ] . attr . name = name ;
zone_dev_attrs [ zone ] . attr . mode = 0644 ;
zone_dev_attrs [ zone ] . show = zone_show ;
zone_dev_attrs [ zone ] . store = zone_set ;
zone_data [ zone ] . location = zone ;
zone_attrs [ zone ] = & zone_dev_attrs [ zone ] . attr ;
zone_data [ zone ] . attr = & zone_dev_attrs [ zone ] ;
2014-04-04 22:15:42 +04:00
}
zone_attrs [ quirks - > num_zones ] = & dev_attr_lighting_control_state . attr ;
zone_attribute_group . attrs = zone_attrs ;
led_classdev_register ( & dev - > dev , & global_led ) ;
return sysfs_create_group ( & dev - > dev . kobj , & zone_attribute_group ) ;
}
static void alienware_zone_exit ( struct platform_device * dev )
{
platform/x86: alienware-wmi: fix format string overflow warning
gcc points out a possible format string overflow for a large value of 'zone':
drivers/platform/x86/alienware-wmi.c: In function 'alienware_wmi_init':
drivers/platform/x86/alienware-wmi.c:461:24: error: '%02X' directive writing between 2 and 8 bytes into a region of size 6 [-Werror=format-overflow=]
sprintf(buffer, "zone%02X", i);
^~~~
drivers/platform/x86/alienware-wmi.c:461:19: note: directive argument in the range [0, 2147483646]
sprintf(buffer, "zone%02X", i);
^~~~~~~~~~
drivers/platform/x86/alienware-wmi.c:461:3: note: 'sprintf' output between 7 and 13 bytes into a destination of size 10
This replaces the 'int' variable with an 'u8' to make sure
it always fits, renaming the variable to 'zone' for clarity.
Unfortunately, gcc-7.1.1 still warns about it with that change, which
seems to be unintended by the gcc developers. I have opened a bug
against gcc with a reduced test case. As a workaround, I also
change the format string to use "%02hhX", which shuts up the
warning in that version.
Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81483
Link: https://patchwork.ozlabs.org/patch/788415/
Suggested-by: Andy Shevchenko <andy@infradead.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
[andy: added empty lines after u8 zone; definitions]
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
2017-07-20 19:00:51 +03:00
u8 zone ;
2014-04-04 22:15:42 +04:00
sysfs_remove_group ( & dev - > dev . kobj , & zone_attribute_group ) ;
led_classdev_unregister ( & global_led ) ;
if ( zone_dev_attrs ) {
platform/x86: alienware-wmi: fix format string overflow warning
gcc points out a possible format string overflow for a large value of 'zone':
drivers/platform/x86/alienware-wmi.c: In function 'alienware_wmi_init':
drivers/platform/x86/alienware-wmi.c:461:24: error: '%02X' directive writing between 2 and 8 bytes into a region of size 6 [-Werror=format-overflow=]
sprintf(buffer, "zone%02X", i);
^~~~
drivers/platform/x86/alienware-wmi.c:461:19: note: directive argument in the range [0, 2147483646]
sprintf(buffer, "zone%02X", i);
^~~~~~~~~~
drivers/platform/x86/alienware-wmi.c:461:3: note: 'sprintf' output between 7 and 13 bytes into a destination of size 10
This replaces the 'int' variable with an 'u8' to make sure
it always fits, renaming the variable to 'zone' for clarity.
Unfortunately, gcc-7.1.1 still warns about it with that change, which
seems to be unintended by the gcc developers. I have opened a bug
against gcc with a reduced test case. As a workaround, I also
change the format string to use "%02hhX", which shuts up the
warning in that version.
Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81483
Link: https://patchwork.ozlabs.org/patch/788415/
Suggested-by: Andy Shevchenko <andy@infradead.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
[andy: added empty lines after u8 zone; definitions]
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
2017-07-20 19:00:51 +03:00
for ( zone = 0 ; zone < quirks - > num_zones ; zone + + )
kfree ( zone_dev_attrs [ zone ] . attr . name ) ;
2014-04-04 22:15:42 +04:00
}
kfree ( zone_dev_attrs ) ;
kfree ( zone_data ) ;
kfree ( zone_attrs ) ;
}
2016-02-03 00:38:54 +03:00
static acpi_status alienware_wmax_command ( struct wmax_basic_args * in_args ,
2014-05-08 00:08:10 +04:00
u32 command , int * out_data )
2014-04-04 22:15:42 +04:00
{
acpi_status status ;
union acpi_object * obj ;
2014-05-08 00:08:10 +04:00
struct acpi_buffer input ;
struct acpi_buffer output ;
input . length = ( acpi_size ) sizeof ( * in_args ) ;
input . pointer = in_args ;
2019-03-30 03:17:12 +03:00
if ( out_data ) {
2014-05-08 00:08:10 +04:00
output . length = ACPI_ALLOCATE_BUFFER ;
output . pointer = NULL ;
2017-06-22 01:01:35 +03:00
status = wmi_evaluate_method ( WMAX_CONTROL_GUID , 0 ,
2014-05-08 00:08:10 +04:00
command , & input , & output ) ;
2019-03-30 03:17:12 +03:00
if ( ACPI_SUCCESS ( status ) ) {
obj = ( union acpi_object * ) output . pointer ;
if ( obj & & obj - > type = = ACPI_TYPE_INTEGER )
* out_data = ( u32 ) obj - > integer . value ;
}
kfree ( output . pointer ) ;
} else {
2017-06-22 01:01:35 +03:00
status = wmi_evaluate_method ( WMAX_CONTROL_GUID , 0 ,
2014-05-08 00:08:10 +04:00
command , & input , NULL ) ;
}
return status ;
}
2016-02-03 00:38:54 +03:00
/*
* The HDMI mux sysfs node indicates the status of the HDMI input mux .
* It can toggle between standard system GPU output and HDMI input .
*/
2014-05-08 00:08:10 +04:00
static ssize_t show_hdmi_cable ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
acpi_status status ;
u32 out_data ;
2016-02-03 00:38:54 +03:00
struct wmax_basic_args in_args = {
2014-04-04 22:15:42 +04:00
. arg = 0 ,
} ;
2014-05-08 00:08:10 +04:00
status =
2016-02-03 00:38:54 +03:00
alienware_wmax_command ( & in_args , WMAX_METHOD_HDMI_CABLE ,
2014-05-08 00:08:10 +04:00
( u32 * ) & out_data ) ;
if ( ACPI_SUCCESS ( status ) ) {
if ( out_data = = 0 )
return scnprintf ( buf , PAGE_SIZE ,
" [unconnected] connected unknown \n " ) ;
else if ( out_data = = 1 )
return scnprintf ( buf , PAGE_SIZE ,
" unconnected [connected] unknown \n " ) ;
}
pr_err ( " alienware-wmi: unknown HDMI cable status: %d \n " , status ) ;
return scnprintf ( buf , PAGE_SIZE , " unconnected connected [unknown] \n " ) ;
}
static ssize_t show_hdmi_source ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
acpi_status status ;
u32 out_data ;
2016-02-03 00:38:54 +03:00
struct wmax_basic_args in_args = {
2014-05-08 00:08:10 +04:00
. arg = 0 ,
} ;
status =
2016-02-03 00:38:54 +03:00
alienware_wmax_command ( & in_args , WMAX_METHOD_HDMI_STATUS ,
2014-05-08 00:08:10 +04:00
( u32 * ) & out_data ) ;
2014-04-04 22:15:42 +04:00
if ( ACPI_SUCCESS ( status ) ) {
2014-05-08 00:08:10 +04:00
if ( out_data = = 1 )
2014-04-04 22:15:42 +04:00
return scnprintf ( buf , PAGE_SIZE ,
" [input] gpu unknown \n " ) ;
2014-05-08 00:08:10 +04:00
else if ( out_data = = 2 )
2014-04-04 22:15:42 +04:00
return scnprintf ( buf , PAGE_SIZE ,
" input [gpu] unknown \n " ) ;
}
2019-04-24 12:44:18 +03:00
pr_err ( " alienware-wmi: unknown HDMI source status: %u \n " , status ) ;
2014-04-04 22:15:42 +04:00
return scnprintf ( buf , PAGE_SIZE , " input gpu [unknown] \n " ) ;
}
2014-05-08 00:08:10 +04:00
static ssize_t toggle_hdmi_source ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
2014-04-04 22:15:42 +04:00
{
acpi_status status ;
2016-02-03 00:38:54 +03:00
struct wmax_basic_args args ;
2014-04-04 22:15:42 +04:00
if ( strcmp ( buf , " gpu \n " ) = = 0 )
args . arg = 1 ;
else if ( strcmp ( buf , " input \n " ) = = 0 )
args . arg = 2 ;
else
args . arg = 3 ;
pr_debug ( " alienware-wmi: setting hdmi to %d : %s " , args . arg , buf ) ;
2014-05-08 00:08:10 +04:00
2016-02-03 00:38:54 +03:00
status = alienware_wmax_command ( & args , WMAX_METHOD_HDMI_SOURCE , NULL ) ;
2014-05-08 00:08:10 +04:00
2014-04-04 22:15:42 +04:00
if ( ACPI_FAILURE ( status ) )
pr_err ( " alienware-wmi: HDMI toggle failed: results: %u \n " ,
status ) ;
return count ;
}
2014-05-08 00:08:10 +04:00
static DEVICE_ATTR ( cable , S_IRUGO , show_hdmi_cable , NULL ) ;
static DEVICE_ATTR ( source , S_IRUGO | S_IWUSR , show_hdmi_source ,
toggle_hdmi_source ) ;
static struct attribute * hdmi_attrs [ ] = {
& dev_attr_cable . attr ,
& dev_attr_source . attr ,
NULL ,
} ;
2014-04-04 22:15:42 +04:00
2017-07-11 13:48:17 +03:00
static const struct attribute_group hdmi_attribute_group = {
2014-05-08 00:08:10 +04:00
. name = " hdmi " ,
. attrs = hdmi_attrs ,
} ;
static void remove_hdmi ( struct platform_device * dev )
2014-04-04 22:15:42 +04:00
{
2014-07-24 08:19:23 +04:00
if ( quirks - > hdmi_mux > 0 )
sysfs_remove_group ( & dev - > dev . kobj , & hdmi_attribute_group ) ;
2014-04-04 22:15:42 +04:00
}
2014-05-08 00:08:10 +04:00
static int create_hdmi ( struct platform_device * dev )
2014-04-04 22:15:42 +04:00
{
2014-05-08 00:08:10 +04:00
int ret ;
ret = sysfs_create_group ( & dev - > dev . kobj , & hdmi_attribute_group ) ;
2014-04-04 22:15:42 +04:00
if ( ret )
2016-02-03 00:38:57 +03:00
remove_hdmi ( dev ) ;
2014-04-04 22:15:42 +04:00
return ret ;
}
2016-02-03 00:38:54 +03:00
/*
* Alienware GFX amplifier support
* - Currently supports reading cable status
* - Leaving expansion room to possibly support dock / undock events later
*/
static ssize_t show_amplifier_status ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
acpi_status status ;
u32 out_data ;
struct wmax_basic_args in_args = {
. arg = 0 ,
} ;
status =
alienware_wmax_command ( & in_args , WMAX_METHOD_AMPLIFIER_CABLE ,
( u32 * ) & out_data ) ;
if ( ACPI_SUCCESS ( status ) ) {
if ( out_data = = 0 )
return scnprintf ( buf , PAGE_SIZE ,
" [unconnected] connected unknown \n " ) ;
else if ( out_data = = 1 )
return scnprintf ( buf , PAGE_SIZE ,
" unconnected [connected] unknown \n " ) ;
}
pr_err ( " alienware-wmi: unknown amplifier cable status: %d \n " , status ) ;
return scnprintf ( buf , PAGE_SIZE , " unconnected connected [unknown] \n " ) ;
}
static DEVICE_ATTR ( status , S_IRUGO , show_amplifier_status , NULL ) ;
static struct attribute * amplifier_attrs [ ] = {
& dev_attr_status . attr ,
NULL ,
} ;
2017-07-11 13:48:17 +03:00
static const struct attribute_group amplifier_attribute_group = {
2016-02-03 00:38:54 +03:00
. name = " amplifier " ,
. attrs = amplifier_attrs ,
} ;
static void remove_amplifier ( struct platform_device * dev )
{
if ( quirks - > amplifier > 0 )
sysfs_remove_group ( & dev - > dev . kobj , & amplifier_attribute_group ) ;
}
static int create_amplifier ( struct platform_device * dev )
{
int ret ;
ret = sysfs_create_group ( & dev - > dev . kobj , & amplifier_attribute_group ) ;
if ( ret )
remove_amplifier ( dev ) ;
return ret ;
}
2016-02-03 00:38:55 +03:00
/*
* Deep Sleep Control support
* - Modifies BIOS setting for deep sleep control allowing extra wakeup events
*/
static ssize_t show_deepsleep_status ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
acpi_status status ;
u32 out_data ;
struct wmax_basic_args in_args = {
. arg = 0 ,
} ;
status = alienware_wmax_command ( & in_args , WMAX_METHOD_DEEP_SLEEP_STATUS ,
( u32 * ) & out_data ) ;
if ( ACPI_SUCCESS ( status ) ) {
if ( out_data = = 0 )
return scnprintf ( buf , PAGE_SIZE ,
" [disabled] s5 s5_s4 \n " ) ;
else if ( out_data = = 1 )
return scnprintf ( buf , PAGE_SIZE ,
" disabled [s5] s5_s4 \n " ) ;
else if ( out_data = = 2 )
return scnprintf ( buf , PAGE_SIZE ,
" disabled s5 [s5_s4] \n " ) ;
}
pr_err ( " alienware-wmi: unknown deep sleep status: %d \n " , status ) ;
return scnprintf ( buf , PAGE_SIZE , " disabled s5 s5_s4 [unknown] \n " ) ;
}
static ssize_t toggle_deepsleep ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t count )
{
acpi_status status ;
struct wmax_basic_args args ;
if ( strcmp ( buf , " disabled \n " ) = = 0 )
args . arg = 0 ;
else if ( strcmp ( buf , " s5 \n " ) = = 0 )
args . arg = 1 ;
else
args . arg = 2 ;
pr_debug ( " alienware-wmi: setting deep sleep to %d : %s " , args . arg , buf ) ;
status = alienware_wmax_command ( & args , WMAX_METHOD_DEEP_SLEEP_CONTROL ,
NULL ) ;
if ( ACPI_FAILURE ( status ) )
pr_err ( " alienware-wmi: deep sleep control failed: results: %u \n " ,
status ) ;
return count ;
}
static DEVICE_ATTR ( deepsleep , S_IRUGO | S_IWUSR , show_deepsleep_status , toggle_deepsleep ) ;
static struct attribute * deepsleep_attrs [ ] = {
& dev_attr_deepsleep . attr ,
NULL ,
} ;
2017-07-11 13:48:17 +03:00
static const struct attribute_group deepsleep_attribute_group = {
2016-02-03 00:38:55 +03:00
. name = " deepsleep " ,
. attrs = deepsleep_attrs ,
} ;
static void remove_deepsleep ( struct platform_device * dev )
{
if ( quirks - > deepslp > 0 )
sysfs_remove_group ( & dev - > dev . kobj , & deepsleep_attribute_group ) ;
}
static int create_deepsleep ( struct platform_device * dev )
{
int ret ;
ret = sysfs_create_group ( & dev - > dev . kobj , & deepsleep_attribute_group ) ;
if ( ret )
remove_deepsleep ( dev ) ;
return ret ;
}
2014-04-04 22:15:42 +04:00
static int __init alienware_wmi_init ( void )
{
int ret ;
if ( wmi_has_guid ( LEGACY_CONTROL_GUID ) )
interface = LEGACY ;
else if ( wmi_has_guid ( WMAX_CONTROL_GUID ) )
interface = WMAX ;
else {
pr_warn ( " alienware-wmi: No known WMI GUID found \n " ) ;
return - ENODEV ;
}
dmi_check_system ( alienware_quirks ) ;
if ( quirks = = NULL )
quirks = & quirk_unknown ;
ret = platform_driver_register ( & platform_driver ) ;
if ( ret )
goto fail_platform_driver ;
platform_device = platform_device_alloc ( " alienware-wmi " , - 1 ) ;
if ( ! platform_device ) {
ret = - ENOMEM ;
goto fail_platform_device1 ;
}
ret = platform_device_add ( platform_device ) ;
if ( ret )
goto fail_platform_device2 ;
2014-07-24 08:19:23 +04:00
if ( quirks - > hdmi_mux > 0 ) {
2014-05-08 00:08:10 +04:00
ret = create_hdmi ( platform_device ) ;
2014-04-04 22:15:42 +04:00
if ( ret )
goto fail_prep_hdmi ;
}
2016-02-03 00:38:54 +03:00
if ( quirks - > amplifier > 0 ) {
ret = create_amplifier ( platform_device ) ;
if ( ret )
goto fail_prep_amplifier ;
}
2016-02-03 00:38:55 +03:00
if ( quirks - > deepslp > 0 ) {
ret = create_deepsleep ( platform_device ) ;
if ( ret )
goto fail_prep_deepsleep ;
}
2014-04-04 22:15:42 +04:00
ret = alienware_zone_init ( platform_device ) ;
if ( ret )
goto fail_prep_zones ;
return 0 ;
fail_prep_zones :
alienware_zone_exit ( platform_device ) ;
2016-02-03 00:38:55 +03:00
fail_prep_deepsleep :
2016-02-03 00:38:54 +03:00
fail_prep_amplifier :
2014-04-04 22:15:42 +04:00
fail_prep_hdmi :
platform_device_del ( platform_device ) ;
fail_platform_device2 :
platform_device_put ( platform_device ) ;
fail_platform_device1 :
platform_driver_unregister ( & platform_driver ) ;
fail_platform_driver :
return ret ;
}
module_init ( alienware_wmi_init ) ;
static void __exit alienware_wmi_exit ( void )
{
if ( platform_device ) {
2014-04-04 23:40:20 +04:00
alienware_zone_exit ( platform_device ) ;
remove_hdmi ( platform_device ) ;
2014-04-04 22:15:42 +04:00
platform_device_unregister ( platform_device ) ;
platform_driver_unregister ( & platform_driver ) ;
}
}
module_exit ( alienware_wmi_exit ) ;