mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-04 18:09:57 +00:00
sony-laptop: cache handles and report them via sysfs
Avoid calling into acpi each time we need to lookup a method handle and report the available handles to ease collection of information when debugging issues. Also move initialization of the platform driver earlier to allow adding files from other setup functions. Signed-off-by: Mattia Dongili <malattia@linux.it> Signed-off-by: Matthew Garrett <mjg@redhat.com>
This commit is contained in:
parent
3672329c36
commit
2a4f0c81ad
1 changed files with 81 additions and 16 deletions
|
@ -727,20 +727,79 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int sony_find_snc_handle(int handle)
|
||||
struct sony_nc_handles {
|
||||
u16 cap[0x10];
|
||||
struct device_attribute devattr;
|
||||
};
|
||||
|
||||
struct sony_nc_handles *handles;
|
||||
|
||||
static ssize_t sony_nc_handles_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buffer)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
|
||||
len += snprintf(buffer + len, PAGE_SIZE - len, "0x%.4x ",
|
||||
handles->cap[i]);
|
||||
}
|
||||
len += snprintf(buffer + len, PAGE_SIZE - len, "\n");
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int sony_nc_handles_setup(struct platform_device *pd)
|
||||
{
|
||||
int i;
|
||||
int result;
|
||||
|
||||
for (i = 0x20; i < 0x30; i++) {
|
||||
acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result);
|
||||
if (result == handle) {
|
||||
dprintk("found handle 0x%.4x (offset: 0x%.2x)\n",
|
||||
handle, i - 0x20);
|
||||
return i-0x20;
|
||||
handles = kzalloc(sizeof(*handles), GFP_KERNEL);
|
||||
|
||||
sysfs_attr_init(&handles->devattr.attr);
|
||||
handles->devattr.attr.name = "handles";
|
||||
handles->devattr.attr.mode = S_IRUGO;
|
||||
handles->devattr.show = sony_nc_handles_show;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
|
||||
if (!acpi_callsetfunc(sony_nc_acpi_handle,
|
||||
"SN00", i + 0x20, &result)) {
|
||||
dprintk("caching handle 0x%.4x (offset: 0x%.2x)\n",
|
||||
result, i);
|
||||
handles->cap[i] = result;
|
||||
}
|
||||
}
|
||||
|
||||
/* allow reading capabilities via sysfs */
|
||||
if (device_create_file(&pd->dev, &handles->devattr)) {
|
||||
kfree(handles);
|
||||
handles = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sony_nc_handles_cleanup(struct platform_device *pd)
|
||||
{
|
||||
if (handles) {
|
||||
device_remove_file(&pd->dev, &handles->devattr);
|
||||
kfree(handles);
|
||||
handles = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sony_find_snc_handle(int handle)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 0x10; i++) {
|
||||
if (handles->cap[i] == handle) {
|
||||
dprintk("found handle 0x%.4x (offset: 0x%.2x)\n",
|
||||
handle, i);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
dprintk("handle 0x%.4x not found\n", handle);
|
||||
return -1;
|
||||
}
|
||||
|
@ -1274,6 +1333,10 @@ static int sony_nc_add(struct acpi_device *device)
|
|||
goto outwalk;
|
||||
}
|
||||
|
||||
result = sony_pf_add();
|
||||
if (result)
|
||||
goto outpresent;
|
||||
|
||||
if (debug) {
|
||||
status = acpi_walk_namespace(ACPI_TYPE_METHOD,
|
||||
sony_nc_acpi_handle, 1, sony_walk_callback,
|
||||
|
@ -1281,7 +1344,7 @@ static int sony_nc_add(struct acpi_device *device)
|
|||
if (ACPI_FAILURE(status)) {
|
||||
pr_warn(DRV_PFX "unable to walk acpi resources\n");
|
||||
result = -ENODEV;
|
||||
goto outwalk;
|
||||
goto outpresent;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1294,6 +1357,8 @@ static int sony_nc_add(struct acpi_device *device)
|
|||
if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
|
||||
&handle))) {
|
||||
dprintk("Doing SNC setup\n");
|
||||
if (sony_nc_handles_setup(sony_pf_device))
|
||||
goto outpresent;
|
||||
sony_nc_function_setup(device);
|
||||
sony_nc_rfkill_setup(device);
|
||||
}
|
||||
|
@ -1302,7 +1367,7 @@ static int sony_nc_add(struct acpi_device *device)
|
|||
result = sony_laptop_setup_input(device);
|
||||
if (result) {
|
||||
pr_err(DRV_PFX "Unable to create input devices.\n");
|
||||
goto outwalk;
|
||||
goto outsnc;
|
||||
}
|
||||
|
||||
if (acpi_video_backlight_support()) {
|
||||
|
@ -1330,10 +1395,6 @@ static int sony_nc_add(struct acpi_device *device)
|
|||
|
||||
}
|
||||
|
||||
result = sony_pf_add();
|
||||
if (result)
|
||||
goto outbacklight;
|
||||
|
||||
/* create sony_pf sysfs attributes related to the SNC device */
|
||||
for (item = sony_nc_values; item->name; ++item) {
|
||||
|
||||
|
@ -1379,14 +1440,17 @@ static int sony_nc_add(struct acpi_device *device)
|
|||
for (item = sony_nc_values; item->name; ++item) {
|
||||
device_remove_file(&sony_pf_device->dev, &item->devattr);
|
||||
}
|
||||
sony_pf_remove();
|
||||
|
||||
outbacklight:
|
||||
if (sony_backlight_device)
|
||||
backlight_device_unregister(sony_backlight_device);
|
||||
|
||||
sony_laptop_remove_input();
|
||||
|
||||
outsnc:
|
||||
sony_nc_handles_cleanup(sony_pf_device);
|
||||
|
||||
outpresent:
|
||||
sony_pf_remove();
|
||||
|
||||
outwalk:
|
||||
sony_nc_rfkill_cleanup();
|
||||
return result;
|
||||
|
@ -1405,6 +1469,7 @@ static int sony_nc_remove(struct acpi_device *device, int type)
|
|||
device_remove_file(&sony_pf_device->dev, &item->devattr);
|
||||
}
|
||||
|
||||
sony_nc_handles_cleanup(sony_pf_device);
|
||||
sony_pf_remove();
|
||||
sony_laptop_remove_input();
|
||||
sony_nc_rfkill_cleanup();
|
||||
|
|
Loading…
Reference in a new issue