aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAbhay Salunke <Abhay_Salunke@dell.com>2006-01-14 16:21:14 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-14 21:27:13 -0500
commit2c5608404e66047bbcd9b7788e7f3ee2555c8639 (patch)
treed6d38c404010a872795c919c59115fa6d278a54c /drivers
parentd063389ecf20e5c20be91a0007656deb9fc38a1c (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.c26
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 @@
49MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); 49MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
50MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); 50MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
51MODULE_LICENSE("GPL"); 51MODULE_LICENSE("GPL");
52MODULE_VERSION("3.1"); 52MODULE_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
565static void callbackfn_rbu(const struct firmware *fw, void *context) 565static 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
606static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, 595static 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}