diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2007-11-05 11:43:30 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-11-14 11:53:35 -0500 |
commit | f51e83916a0a022d3d0ea39ae2f877c703032923 (patch) | |
tree | 0341762efa85726c476c32efa118a53097a9e04f /drivers/acpi/video.c | |
parent | 91c05c667b2d8e43e0bbc5f269bf45d4821001d6 (diff) |
ACPI: video - add missing input_free_device()
If input_register_device() fails input_free_device() must
be called to release memory allocated for the device.
Also consolidate error handling in acpi_bus_video_add()
and handle input_allocate_device() failures.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Acked-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/video.c')
-rw-r--r-- | drivers/acpi/video.c | 69 |
1 files changed, 34 insertions, 35 deletions
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index c0e4e7423fcd..be66a7c04d38 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -1897,14 +1897,10 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) | |||
1897 | static int instance; | 1897 | static int instance; |
1898 | static int acpi_video_bus_add(struct acpi_device *device) | 1898 | static int acpi_video_bus_add(struct acpi_device *device) |
1899 | { | 1899 | { |
1900 | int result = 0; | 1900 | acpi_status status; |
1901 | acpi_status status = 0; | 1901 | struct acpi_video_bus *video; |
1902 | struct acpi_video_bus *video = NULL; | ||
1903 | struct input_dev *input; | 1902 | struct input_dev *input; |
1904 | 1903 | int error; | |
1905 | |||
1906 | if (!device) | ||
1907 | return -EINVAL; | ||
1908 | 1904 | ||
1909 | video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); | 1905 | video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); |
1910 | if (!video) | 1906 | if (!video) |
@@ -1923,13 +1919,13 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1923 | acpi_driver_data(device) = video; | 1919 | acpi_driver_data(device) = video; |
1924 | 1920 | ||
1925 | acpi_video_bus_find_cap(video); | 1921 | acpi_video_bus_find_cap(video); |
1926 | result = acpi_video_bus_check(video); | 1922 | error = acpi_video_bus_check(video); |
1927 | if (result) | 1923 | if (error) |
1928 | goto end; | 1924 | goto err_free_video; |
1929 | 1925 | ||
1930 | result = acpi_video_bus_add_fs(device); | 1926 | error = acpi_video_bus_add_fs(device); |
1931 | if (result) | 1927 | if (error) |
1932 | goto end; | 1928 | goto err_free_video; |
1933 | 1929 | ||
1934 | init_MUTEX(&video->sem); | 1930 | init_MUTEX(&video->sem); |
1935 | INIT_LIST_HEAD(&video->video_device_list); | 1931 | INIT_LIST_HEAD(&video->video_device_list); |
@@ -1943,16 +1939,15 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1943 | if (ACPI_FAILURE(status)) { | 1939 | if (ACPI_FAILURE(status)) { |
1944 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 1940 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
1945 | "Error installing notify handler\n")); | 1941 | "Error installing notify handler\n")); |
1946 | acpi_video_bus_stop_devices(video); | 1942 | error = -ENODEV; |
1947 | acpi_video_bus_put_devices(video); | 1943 | goto err_stop_video; |
1948 | kfree(video->attached_array); | ||
1949 | acpi_video_bus_remove_fs(device); | ||
1950 | result = -ENODEV; | ||
1951 | goto end; | ||
1952 | } | 1944 | } |
1953 | 1945 | ||
1954 | |||
1955 | video->input = input = input_allocate_device(); | 1946 | video->input = input = input_allocate_device(); |
1947 | if (!input) { | ||
1948 | error = -ENOMEM; | ||
1949 | goto err_uninstall_notify; | ||
1950 | } | ||
1956 | 1951 | ||
1957 | snprintf(video->phys, sizeof(video->phys), | 1952 | snprintf(video->phys, sizeof(video->phys), |
1958 | "%s/video/input0", acpi_device_hid(video->device)); | 1953 | "%s/video/input0", acpi_device_hid(video->device)); |
@@ -1972,18 +1967,10 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1972 | set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); | 1967 | set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); |
1973 | set_bit(KEY_DISPLAY_OFF, input->keybit); | 1968 | set_bit(KEY_DISPLAY_OFF, input->keybit); |
1974 | set_bit(KEY_UNKNOWN, input->keybit); | 1969 | set_bit(KEY_UNKNOWN, input->keybit); |
1975 | result = input_register_device(input); | ||
1976 | if (result) { | ||
1977 | acpi_remove_notify_handler(video->device->handle, | ||
1978 | ACPI_DEVICE_NOTIFY, | ||
1979 | acpi_video_bus_notify); | ||
1980 | acpi_video_bus_stop_devices(video); | ||
1981 | acpi_video_bus_put_devices(video); | ||
1982 | kfree(video->attached_array); | ||
1983 | acpi_video_bus_remove_fs(device); | ||
1984 | goto end; | ||
1985 | } | ||
1986 | 1970 | ||
1971 | error = input_register_device(input); | ||
1972 | if (error) | ||
1973 | goto err_free_input_dev; | ||
1987 | 1974 | ||
1988 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", | 1975 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", |
1989 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), | 1976 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), |
@@ -1991,11 +1978,23 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1991 | video->flags.rom ? "yes" : "no", | 1978 | video->flags.rom ? "yes" : "no", |
1992 | video->flags.post ? "yes" : "no"); | 1979 | video->flags.post ? "yes" : "no"); |
1993 | 1980 | ||
1994 | end: | 1981 | return 0; |
1995 | if (result) | 1982 | |
1996 | kfree(video); | 1983 | err_free_input_dev: |
1984 | input_free_device(input); | ||
1985 | err_uninstall_notify: | ||
1986 | acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, | ||
1987 | acpi_video_bus_notify); | ||
1988 | err_stop_video: | ||
1989 | acpi_video_bus_stop_devices(video); | ||
1990 | acpi_video_bus_put_devices(video); | ||
1991 | kfree(video->attached_array); | ||
1992 | acpi_video_bus_remove_fs(device); | ||
1993 | err_free_video: | ||
1994 | kfree(video); | ||
1995 | acpi_driver_data(device) = NULL; | ||
1997 | 1996 | ||
1998 | return result; | 1997 | return error; |
1999 | } | 1998 | } |
2000 | 1999 | ||
2001 | static int acpi_video_bus_remove(struct acpi_device *device, int type) | 2000 | static int acpi_video_bus_remove(struct acpi_device *device, int type) |