diff options
author | Abhay Salunke <Abhay_Salunke@dell.com> | 2006-01-14 16:21:14 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-14 21:27:13 -0500 |
commit | 2c5608404e66047bbcd9b7788e7f3ee2555c8639 (patch) | |
tree | d6d38c404010a872795c919c59115fa6d278a54c /drivers | |
parent | d063389ecf20e5c20be91a0007656deb9fc38a1c (diff) |
[PATCH] dell_rbu: fix Bug 5854
This fixes http://bugzilla.kernel.org/show_bug.cgi?id=5854
Root cause:
The dell_rbu driver creates entries in /sys/class/firmware/dell_rbu/ by
calling request_firmware_nowait (without hotplug ) this function inturn
starts a kernel thread which creates the entries in
/sys/class/firmware/dell_rbu/loading , data and the thread waits on the
user action to return control back to the callback fucntion of dell_rbu.
The thread calls wait_on_completion which puts it in a D state until the
user action happens. If there is no user action happening the load average
goes up as the thread D state is taken in to account. Also after
downloading the BIOS image the enrties go away momentarily but they are
recreated from the callback function in dell_rbu. This causes the thread
to get recreated causing the load average to permenently stay around 1.
Fix:
The dell_rbu also creates the entry
/sys/devices/platform/dell_rbu/image_type at driver load time. The image
type by default is mono if required the user can echo packet to image_type
to make the BIOS update mechanism using packets. Also by echoing init in
to image_type the /sys/class/firmware/dell_rbu entries can be created.
The driver code was changed to not create /sys/class/firmware/dell_rbu
entries during load time, and also to not create the above entries from the
callback function. The entries are only created by echoing init to
/sys/devices/platform/dell_rbu/image_type The user now needs to create the
entries to download the image monolithic or packet. This fixes the issue
since the kernel thread only is created when ever the user is ready to
download the BIOS image; this minimizes the life span of the kernel thread
and the load average goes back to normal.
Signed off by Abhay Salunke <abhay_salunke@dell.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/firmware/dell_rbu.c | 26 |
1 files changed, 4 insertions, 22 deletions
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index dfedb777d8c..fdb8b042e64 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c | |||
@@ -49,7 +49,7 @@ | |||
49 | MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); | 49 | MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); |
50 | MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); | 50 | MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); |
51 | MODULE_LICENSE("GPL"); | 51 | MODULE_LICENSE("GPL"); |
52 | MODULE_VERSION("3.1"); | 52 | MODULE_VERSION("3.2"); |
53 | 53 | ||
54 | #define BIOS_SCAN_LIMIT 0xffffffff | 54 | #define BIOS_SCAN_LIMIT 0xffffffff |
55 | #define MAX_IMAGE_LENGTH 16 | 55 | #define MAX_IMAGE_LENGTH 16 |
@@ -564,12 +564,10 @@ static ssize_t read_rbu_data(struct kobject *kobj, char *buffer, | |||
564 | 564 | ||
565 | static void callbackfn_rbu(const struct firmware *fw, void *context) | 565 | static void callbackfn_rbu(const struct firmware *fw, void *context) |
566 | { | 566 | { |
567 | int rc = 0; | 567 | rbu_data.entry_created = 0; |
568 | 568 | ||
569 | if (!fw || !fw->size) { | 569 | if (!fw || !fw->size) |
570 | rbu_data.entry_created = 0; | ||
571 | return; | 570 | return; |
572 | } | ||
573 | 571 | ||
574 | spin_lock(&rbu_data.lock); | 572 | spin_lock(&rbu_data.lock); |
575 | if (!strcmp(image_type, "mono")) { | 573 | if (!strcmp(image_type, "mono")) { |
@@ -592,15 +590,6 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) | |||
592 | } else | 590 | } else |
593 | pr_debug("invalid image type specified.\n"); | 591 | pr_debug("invalid image type specified.\n"); |
594 | spin_unlock(&rbu_data.lock); | 592 | spin_unlock(&rbu_data.lock); |
595 | |||
596 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | ||
597 | "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); | ||
598 | if (rc) | ||
599 | printk(KERN_ERR | ||
600 | "dell_rbu:%s request_firmware_nowait failed" | ||
601 | " %d\n", __FUNCTION__, rc); | ||
602 | else | ||
603 | rbu_data.entry_created = 1; | ||
604 | } | 593 | } |
605 | 594 | ||
606 | static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, | 595 | static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, |
@@ -735,14 +724,7 @@ static int __init dcdrbu_init(void) | |||
735 | sysfs_create_bin_file(&rbu_device->dev.kobj, | 724 | sysfs_create_bin_file(&rbu_device->dev.kobj, |
736 | &rbu_packet_size_attr); | 725 | &rbu_packet_size_attr); |
737 | 726 | ||
738 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | 727 | rbu_data.entry_created = 0; |
739 | "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); | ||
740 | if (rc) | ||
741 | printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait" | ||
742 | " failed %d\n", __FUNCTION__, rc); | ||
743 | else | ||
744 | rbu_data.entry_created = 1; | ||
745 | |||
746 | return rc; | 728 | return rc; |
747 | 729 | ||
748 | } | 730 | } |