aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbhay Salunke <Abhay_Salunke@dell.com>2005-09-16 22:28:04 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-17 14:50:02 -0400
commite61c0e336f3931842f09e6709d76146bfd81184e (patch)
treec5f1083fcf162f80080874b3934bcd7a48893f9f
parent3013449243adc3421b507696e5d247a3d292ee0c (diff)
[PATCH] dell_rbu: enhancements and fixes
BUG fixes: The driver used to allocate memory with spinlock held which has been fixed in this patch. The driver was printing the entire buffer when it received a invalid entry in image_type. The fix is to only print a warning message and not the buffer. Usability enhancements: It is possible that due to user error the /sys/class/firmware/dell_rbu entries might be missing, this can happen if the user does the following echo 1 > /sys/class/firmware/dell_rbu/loading echo 0 > /sys/class/firmware/dell_rbu/loading This will make the entries in /sys/class/firmware/ to disappear and the only way get them back was bby unloading and loading the driver. This patch makes the user recreate these entries by echoing init in to image_type. This patch has been tested with Libsmbios and Dell OpenManage. 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>
-rw-r--r--Documentation/dell_rbu.txt18
-rw-r--r--drivers/firmware/dell_rbu.c251
2 files changed, 167 insertions, 102 deletions
diff --git a/Documentation/dell_rbu.txt b/Documentation/dell_rbu.txt
index bcfa5c35036b..95d7f62e4dbc 100644
--- a/Documentation/dell_rbu.txt
+++ b/Documentation/dell_rbu.txt
@@ -13,6 +13,8 @@ the BIOS on Dell servers (starting from servers sold since 1999), desktops
13and notebooks (starting from those sold in 2005). 13and notebooks (starting from those sold in 2005).
14Please go to http://support.dell.com register and you can find info on 14Please go to http://support.dell.com register and you can find info on
15OpenManage and Dell Update packages (DUP). 15OpenManage and Dell Update packages (DUP).
16Libsmbios can also be used to update BIOS on Dell systems go to
17http://linux.dell.com/libsmbios/ for details.
16 18
17Dell_RBU driver supports BIOS update using the monilothic image and packetized 19Dell_RBU driver supports BIOS update using the monilothic image and packetized
18image methods. In case of moniolithic the driver allocates a contiguous chunk 20image methods. In case of moniolithic the driver allocates a contiguous chunk
@@ -22,8 +24,8 @@ would place each packet in contiguous physical memory. The driver also
22maintains a link list of packets for reading them back. 24maintains a link list of packets for reading them back.
23If the dell_rbu driver is unloaded all the allocated memory is freed. 25If the dell_rbu driver is unloaded all the allocated memory is freed.
24 26
25The rbu driver needs to have an application which will inform the BIOS to 27The rbu driver needs to have an application (as mentioned above)which will
26enable the update in the next system reboot. 28inform the BIOS to enable the update in the next system reboot.
27 29
28The user should not unload the rbu driver after downloading the BIOS image 30The user should not unload the rbu driver after downloading the BIOS image
29or updating. 31or updating.
@@ -42,9 +44,11 @@ In case of packet mechanism the single memory can be broken in smaller chuks
42of contiguous memory and the BIOS image is scattered in these packets. 44of contiguous memory and the BIOS image is scattered in these packets.
43 45
44By default the driver uses monolithic memory for the update type. This can be 46By default the driver uses monolithic memory for the update type. This can be
45changed to contiguous during the driver load time by specifying the load 47changed to packets during the driver load time by specifying the load
46parameter image_type=packet. This can also be changed later as below 48parameter image_type=packet. This can also be changed later as below
47echo packet > /sys/devices/platform/dell_rbu/image_type 49echo packet > /sys/devices/platform/dell_rbu/image_type
50Also echoing either mono ,packet or init in to image_type will free up the
51memory allocated by the driver.
48 52
49Do the steps below to download the BIOS image. 53Do the steps below to download the BIOS image.
501) echo 1 > /sys/class/firmware/dell_rbu/loading 541) echo 1 > /sys/class/firmware/dell_rbu/loading
@@ -53,9 +57,13 @@ Do the steps below to download the BIOS image.
53 57
54The /sys/class/firmware/dell_rbu/ entries will remain till the following is 58The /sys/class/firmware/dell_rbu/ entries will remain till the following is
55done. 59done.
56echo -1 > /sys/class/firmware/dell_rbu/loading 60echo -1 > /sys/class/firmware/dell_rbu/loading.
57
58Until this step is completed the drivr cannot be unloaded. 61Until this step is completed the drivr cannot be unloaded.
62If an user by accident executes steps 1 and 3 above without executing step 2;
63it will make the /sys/class/firmware/dell_rbu/ entries to disappear.
64The entries can be recreated by doing the following
65echo init > /sys/devices/platform/dell_rbu/image_type
66NOTE: echoing init in image_type does not change it original value.
59 67
60Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to 68Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to
61read back the image downloaded. This is useful in case of packet update 69read back the image downloaded. This is useful in case of packet update
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
index 3b865f34a095..9c2c2b199454 100644
--- a/drivers/firmware/dell_rbu.c
+++ b/drivers/firmware/dell_rbu.c
@@ -50,7 +50,7 @@
50MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); 50MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
51MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); 51MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
52MODULE_LICENSE("GPL"); 52MODULE_LICENSE("GPL");
53MODULE_VERSION("1.0"); 53MODULE_VERSION("2.0");
54 54
55#define BIOS_SCAN_LIMIT 0xffffffff 55#define BIOS_SCAN_LIMIT 0xffffffff
56#define MAX_IMAGE_LENGTH 16 56#define MAX_IMAGE_LENGTH 16
@@ -65,10 +65,11 @@ static struct _rbu_data {
65 unsigned long packet_write_count; 65 unsigned long packet_write_count;
66 unsigned long num_packets; 66 unsigned long num_packets;
67 unsigned long packetsize; 67 unsigned long packetsize;
68 int entry_created;
68} rbu_data; 69} rbu_data;
69 70
70static char image_type[MAX_IMAGE_LENGTH] = "mono"; 71static char image_type[MAX_IMAGE_LENGTH + 1] = "mono";
71module_param_string(image_type, image_type, sizeof(image_type), 0); 72module_param_string(image_type, image_type, sizeof (image_type), 0);
72MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet"); 73MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet");
73 74
74struct packet_data { 75struct packet_data {
@@ -84,7 +85,8 @@ static struct platform_device *rbu_device;
84static int context; 85static int context;
85static dma_addr_t dell_rbu_dmaaddr; 86static dma_addr_t dell_rbu_dmaaddr;
86 87
87static void init_packet_head(void) 88static void
89init_packet_head(void)
88{ 90{
89 INIT_LIST_HEAD(&packet_data_head.list); 91 INIT_LIST_HEAD(&packet_data_head.list);
90 rbu_data.packet_write_count = 0; 92 rbu_data.packet_write_count = 0;
@@ -93,7 +95,8 @@ static void init_packet_head(void)
93 rbu_data.packetsize = 0; 95 rbu_data.packetsize = 0;
94} 96}
95 97
96static int fill_last_packet(void *data, size_t length) 98static int
99fill_last_packet(void *data, size_t length)
97{ 100{
98 struct list_head *ptemp_list; 101 struct list_head *ptemp_list;
99 struct packet_data *packet = NULL; 102 struct packet_data *packet = NULL;
@@ -114,7 +117,7 @@ static int fill_last_packet(void *data, size_t length)
114 117
115 if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) { 118 if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) {
116 pr_debug("dell_rbu:%s: packet size data " 119 pr_debug("dell_rbu:%s: packet size data "
117 "overrun\n", __FUNCTION__); 120 "overrun\n", __FUNCTION__);
118 return -EINVAL; 121 return -EINVAL;
119 } 122 }
120 123
@@ -135,7 +138,8 @@ static int fill_last_packet(void *data, size_t length)
135 return 0; 138 return 0;
136} 139}
137 140
138static int create_packet(size_t length) 141static int
142create_packet(size_t length)
139{ 143{
140 struct packet_data *newpacket; 144 struct packet_data *newpacket;
141 int ordernum = 0; 145 int ordernum = 0;
@@ -146,12 +150,14 @@ static int create_packet(size_t length)
146 pr_debug("create_packet: packetsize not specified\n"); 150 pr_debug("create_packet: packetsize not specified\n");
147 return -EINVAL; 151 return -EINVAL;
148 } 152 }
153 spin_unlock(&rbu_data.lock);
154 newpacket = kmalloc(sizeof (struct packet_data), GFP_KERNEL);
155 spin_lock(&rbu_data.lock);
149 156
150 newpacket = kmalloc(sizeof(struct packet_data), GFP_KERNEL);
151 if (!newpacket) { 157 if (!newpacket) {
152 printk(KERN_WARNING 158 printk(KERN_WARNING
153 "dell_rbu:%s: failed to allocate new " 159 "dell_rbu:%s: failed to allocate new "
154 "packet\n", __FUNCTION__); 160 "packet\n", __FUNCTION__);
155 return -ENOMEM; 161 return -ENOMEM;
156 } 162 }
157 163
@@ -160,15 +166,17 @@ static int create_packet(size_t length)
160 * there is no upper limit on memory 166 * there is no upper limit on memory
161 * address for packetized mechanism 167 * address for packetized mechanism
162 */ 168 */
163 newpacket->data = (unsigned char *)__get_free_pages(GFP_KERNEL, 169 spin_unlock(&rbu_data.lock);
164 ordernum); 170 newpacket->data = (unsigned char *) __get_free_pages(GFP_KERNEL,
171 ordernum);
172 spin_lock(&rbu_data.lock);
165 173
166 pr_debug("create_packet: newpacket %p\n", newpacket->data); 174 pr_debug("create_packet: newpacket %p\n", newpacket->data);
167 175
168 if (!newpacket->data) { 176 if (!newpacket->data) {
169 printk(KERN_WARNING 177 printk(KERN_WARNING
170 "dell_rbu:%s: failed to allocate new " 178 "dell_rbu:%s: failed to allocate new "
171 "packet\n", __FUNCTION__); 179 "packet\n", __FUNCTION__);
172 kfree(newpacket); 180 kfree(newpacket);
173 return -ENOMEM; 181 return -ENOMEM;
174 } 182 }
@@ -190,7 +198,8 @@ static int create_packet(size_t length)
190 return 0; 198 return 0;
191} 199}
192 200
193static int packetize_data(void *data, size_t length) 201static int
202packetize_data(void *data, size_t length)
194{ 203{
195 int rc = 0; 204 int rc = 0;
196 205
@@ -206,7 +215,7 @@ static int packetize_data(void *data, size_t length)
206 215
207static int 216static int
208do_packet_read(char *data, struct list_head *ptemp_list, 217do_packet_read(char *data, struct list_head *ptemp_list,
209 int length, int bytes_read, int *list_read_count) 218 int length, int bytes_read, int *list_read_count)
210{ 219{
211 void *ptemp_buf; 220 void *ptemp_buf;
212 struct packet_data *newpacket = NULL; 221 struct packet_data *newpacket = NULL;
@@ -239,7 +248,8 @@ do_packet_read(char *data, struct list_head *ptemp_list,
239 return bytes_copied; 248 return bytes_copied;
240} 249}
241 250
242static int packet_read_list(char *data, size_t * pread_length) 251static int
252packet_read_list(char *data, size_t * pread_length)
243{ 253{
244 struct list_head *ptemp_list; 254 struct list_head *ptemp_list;
245 int temp_count = 0; 255 int temp_count = 0;
@@ -258,8 +268,7 @@ static int packet_read_list(char *data, size_t * pread_length)
258 ptemp_list = (&packet_data_head.list)->next; 268 ptemp_list = (&packet_data_head.list)->next;
259 while (!list_empty(ptemp_list)) { 269 while (!list_empty(ptemp_list)) {
260 bytes_copied = do_packet_read(pdest, ptemp_list, 270 bytes_copied = do_packet_read(pdest, ptemp_list,
261 remaining_bytes, bytes_read, 271 remaining_bytes, bytes_read, &temp_count);
262 &temp_count);
263 remaining_bytes -= bytes_copied; 272 remaining_bytes -= bytes_copied;
264 bytes_read += bytes_copied; 273 bytes_read += bytes_copied;
265 pdest += bytes_copied; 274 pdest += bytes_copied;
@@ -278,7 +287,8 @@ static int packet_read_list(char *data, size_t * pread_length)
278 return 0; 287 return 0;
279} 288}
280 289
281static void packet_empty_list(void) 290static void
291packet_empty_list(void)
282{ 292{
283 struct list_head *ptemp_list; 293 struct list_head *ptemp_list;
284 struct list_head *pnext_list; 294 struct list_head *pnext_list;
@@ -287,7 +297,7 @@ static void packet_empty_list(void)
287 ptemp_list = (&packet_data_head.list)->next; 297 ptemp_list = (&packet_data_head.list)->next;
288 while (!list_empty(ptemp_list)) { 298 while (!list_empty(ptemp_list)) {
289 newpacket = 299 newpacket =
290 list_entry(ptemp_list, struct packet_data, list); 300 list_entry(ptemp_list, struct packet_data, list);
291 pnext_list = ptemp_list->next; 301 pnext_list = ptemp_list->next;
292 list_del(ptemp_list); 302 list_del(ptemp_list);
293 ptemp_list = pnext_list; 303 ptemp_list = pnext_list;
@@ -296,8 +306,8 @@ static void packet_empty_list(void)
296 * to make sure there are no stale RBU packets left in memory 306 * to make sure there are no stale RBU packets left in memory
297 */ 307 */
298 memset(newpacket->data, 0, rbu_data.packetsize); 308 memset(newpacket->data, 0, rbu_data.packetsize);
299 free_pages((unsigned long)newpacket->data, 309 free_pages((unsigned long) newpacket->data,
300 newpacket->ordernum); 310 newpacket->ordernum);
301 kfree(newpacket); 311 kfree(newpacket);
302 } 312 }
303 rbu_data.packet_write_count = 0; 313 rbu_data.packet_write_count = 0;
@@ -310,7 +320,8 @@ static void packet_empty_list(void)
310 * img_update_free: Frees the buffer allocated for storing BIOS image 320 * img_update_free: Frees the buffer allocated for storing BIOS image
311 * Always called with lock held and returned with lock held 321 * Always called with lock held and returned with lock held
312 */ 322 */
313static void img_update_free(void) 323static void
324img_update_free(void)
314{ 325{
315 if (!rbu_data.image_update_buffer) 326 if (!rbu_data.image_update_buffer)
316 return; 327 return;
@@ -319,14 +330,13 @@ static void img_update_free(void)
319 * BIOS image copied in memory. 330 * BIOS image copied in memory.
320 */ 331 */
321 memset(rbu_data.image_update_buffer, 0, 332 memset(rbu_data.image_update_buffer, 0,
322 rbu_data.image_update_buffer_size); 333 rbu_data.image_update_buffer_size);
323 if (rbu_data.dma_alloc == 1) 334 if (rbu_data.dma_alloc == 1)
324 dma_free_coherent(NULL, rbu_data.bios_image_size, 335 dma_free_coherent(NULL, rbu_data.bios_image_size,
325 rbu_data.image_update_buffer, 336 rbu_data.image_update_buffer, dell_rbu_dmaaddr);
326 dell_rbu_dmaaddr);
327 else 337 else
328 free_pages((unsigned long)rbu_data.image_update_buffer, 338 free_pages((unsigned long) rbu_data.image_update_buffer,
329 rbu_data.image_update_ordernum); 339 rbu_data.image_update_ordernum);
330 340
331 /* 341 /*
332 * Re-initialize the rbu_data variables after a free 342 * Re-initialize the rbu_data variables after a free
@@ -348,7 +358,8 @@ static void img_update_free(void)
348 * already allocated size, then that memory is reused. This function is 358 * already allocated size, then that memory is reused. This function is
349 * called with lock held and returns with lock held. 359 * called with lock held and returns with lock held.
350 */ 360 */
351static int img_update_realloc(unsigned long size) 361static int
362img_update_realloc(unsigned long size)
352{ 363{
353 unsigned char *image_update_buffer = NULL; 364 unsigned char *image_update_buffer = NULL;
354 unsigned long rc; 365 unsigned long rc;
@@ -366,7 +377,7 @@ static int img_update_realloc(unsigned long size)
366 */ 377 */
367 if ((size != 0) && (rbu_data.image_update_buffer == NULL)) { 378 if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
368 printk(KERN_ERR "dell_rbu:%s: corruption " 379 printk(KERN_ERR "dell_rbu:%s: corruption "
369 "check failed\n", __FUNCTION__); 380 "check failed\n", __FUNCTION__);
370 return -EINVAL; 381 return -EINVAL;
371 } 382 }
372 /* 383 /*
@@ -385,17 +396,16 @@ static int img_update_realloc(unsigned long size)
385 396
386 ordernum = get_order(size); 397 ordernum = get_order(size);
387 image_update_buffer = 398 image_update_buffer =
388 (unsigned char *)__get_free_pages(GFP_KERNEL, ordernum); 399 (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum);
389 400
390 img_buf_phys_addr = 401 img_buf_phys_addr =
391 (unsigned long)virt_to_phys(image_update_buffer); 402 (unsigned long) virt_to_phys(image_update_buffer);
392 403
393 if (img_buf_phys_addr > BIOS_SCAN_LIMIT) { 404 if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {
394 free_pages((unsigned long)image_update_buffer, ordernum); 405 free_pages((unsigned long) image_update_buffer, ordernum);
395 ordernum = -1; 406 ordernum = -1;
396 image_update_buffer = dma_alloc_coherent(NULL, size, 407 image_update_buffer = dma_alloc_coherent(NULL, size,
397 &dell_rbu_dmaaddr, 408 &dell_rbu_dmaaddr, GFP_KERNEL);
398 GFP_KERNEL);
399 dma_alloc = 1; 409 dma_alloc = 1;
400 } 410 }
401 411
@@ -405,20 +415,21 @@ static int img_update_realloc(unsigned long size)
405 rbu_data.image_update_buffer = image_update_buffer; 415 rbu_data.image_update_buffer = image_update_buffer;
406 rbu_data.image_update_buffer_size = size; 416 rbu_data.image_update_buffer_size = size;
407 rbu_data.bios_image_size = 417 rbu_data.bios_image_size =
408 rbu_data.image_update_buffer_size; 418 rbu_data.image_update_buffer_size;
409 rbu_data.image_update_ordernum = ordernum; 419 rbu_data.image_update_ordernum = ordernum;
410 rbu_data.dma_alloc = dma_alloc; 420 rbu_data.dma_alloc = dma_alloc;
411 rc = 0; 421 rc = 0;
412 } else { 422 } else {
413 pr_debug("Not enough memory for image update:" 423 pr_debug("Not enough memory for image update:"
414 "size = %ld\n", size); 424 "size = %ld\n", size);
415 rc = -ENOMEM; 425 rc = -ENOMEM;
416 } 426 }
417 427
418 return rc; 428 return rc;
419} 429}
420 430
421static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) 431static ssize_t
432read_packet_data(char *buffer, loff_t pos, size_t count)
422{ 433{
423 int retval; 434 int retval;
424 size_t bytes_left; 435 size_t bytes_left;
@@ -438,7 +449,7 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
438 if (pos > imagesize) { 449 if (pos > imagesize) {
439 retval = 0; 450 retval = 0;
440 printk(KERN_WARNING "dell_rbu:read_packet_data: " 451 printk(KERN_WARNING "dell_rbu:read_packet_data: "
441 "data underrun\n"); 452 "data underrun\n");
442 goto read_rbu_data_exit; 453 goto read_rbu_data_exit;
443 } 454 }
444 455
@@ -459,7 +470,8 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
459 return retval; 470 return retval;
460} 471}
461 472
462static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) 473static ssize_t
474read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
463{ 475{
464 unsigned char *ptemp = NULL; 476 unsigned char *ptemp = NULL;
465 size_t bytes_left = 0; 477 size_t bytes_left = 0;
@@ -468,11 +480,11 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
468 480
469 /* check to see if we have something to return */ 481 /* check to see if we have something to return */
470 if ((rbu_data.image_update_buffer == NULL) || 482 if ((rbu_data.image_update_buffer == NULL) ||
471 (rbu_data.bios_image_size == 0)) { 483 (rbu_data.bios_image_size == 0)) {
472 pr_debug("read_rbu_data_mono: image_update_buffer %p ," 484 pr_debug("read_rbu_data_mono: image_update_buffer %p ,"
473 "bios_image_size %lu\n", 485 "bios_image_size %lu\n",
474 rbu_data.image_update_buffer, 486 rbu_data.image_update_buffer,
475 rbu_data.bios_image_size); 487 rbu_data.bios_image_size);
476 ret_count = -ENOMEM; 488 ret_count = -ENOMEM;
477 goto read_rbu_data_exit; 489 goto read_rbu_data_exit;
478 } 490 }
@@ -515,9 +527,46 @@ read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count)
515 return ret_count; 527 return ret_count;
516} 528}
517 529
530static void
531callbackfn_rbu(const struct firmware *fw, void *context)
532{
533 int rc = 0;
534
535 if (!fw || !fw->size) {
536 rbu_data.entry_created = 0;
537 return;
538 }
539
540 spin_lock(&rbu_data.lock);
541 if (!strcmp(image_type, "mono")) {
542 if (!img_update_realloc(fw->size))
543 memcpy(rbu_data.image_update_buffer,
544 fw->data, fw->size);
545 } else if (!strcmp(image_type, "packet")) {
546 if (!rbu_data.packetsize)
547 rbu_data.packetsize = fw->size;
548 else if (rbu_data.packetsize != fw->size) {
549 packet_empty_list();
550 rbu_data.packetsize = fw->size;
551 }
552 packetize_data(fw->data, fw->size);
553 } else
554 pr_debug("invalid image type specified.\n");
555 spin_unlock(&rbu_data.lock);
556
557 rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
558 "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);
559 if (rc)
560 printk(KERN_ERR
561 "dell_rbu:%s request_firmware_nowait failed"
562 " %d\n", __FUNCTION__, rc);
563 else
564 rbu_data.entry_created = 1;
565}
566
518static ssize_t 567static ssize_t
519read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, 568read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos,
520 size_t count) 569 size_t count)
521{ 570{
522 int size = 0; 571 int size = 0;
523 if (!pos) 572 if (!pos)
@@ -527,25 +576,63 @@ read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos,
527 576
528static ssize_t 577static ssize_t
529write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, 578write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos,
530 size_t count) 579 size_t count)
531{ 580{
532 int rc = count; 581 int rc = count;
582 int req_firm_rc = 0;
583 int i;
533 spin_lock(&rbu_data.lock); 584 spin_lock(&rbu_data.lock);
534 585 /*
535 if (strlen(buffer) < MAX_IMAGE_LENGTH) 586 * Find the first newline or space
536 sscanf(buffer, "%s", image_type); 587 */
537 else 588 for (i = 0; i < count; ++i)
538 printk(KERN_WARNING "dell_rbu: image_type is invalid" 589 if (buffer[i] == '\n' || buffer[i] == ' ') {
539 "max chars = %d, \n incoming str--%s-- \n", 590 buffer[i] = '\0';
540 MAX_IMAGE_LENGTH, buffer); 591 break;
592 }
593 if (i == count)
594 buffer[count] = '\0';
595
596 if (strstr(buffer, "mono"))
597 strcpy(image_type, "mono");
598 else if (strstr(buffer, "packet"))
599 strcpy(image_type, "packet");
600 else if (strstr(buffer, "init")) {
601 /*
602 * If due to the user error the driver gets in a bad
603 * state where even though it is loaded , the
604 * /sys/class/firmware/dell_rbu entries are missing.
605 * to cover this situation the user can recreate entries
606 * by writing init to image_type.
607 */
608 if (!rbu_data.entry_created) {
609 spin_unlock(&rbu_data.lock);
610 req_firm_rc = request_firmware_nowait(THIS_MODULE,
611 FW_ACTION_NOHOTPLUG, "dell_rbu",
612 &rbu_device->dev, &context,
613 callbackfn_rbu);
614 if (req_firm_rc) {
615 printk(KERN_ERR
616 "dell_rbu:%s request_firmware_nowait"
617 " failed %d\n", __FUNCTION__, rc);
618 rc = -EIO;
619 } else
620 rbu_data.entry_created = 1;
621
622 spin_lock(&rbu_data.lock);
623 }
624 } else {
625 printk(KERN_WARNING "dell_rbu: image_type is invalid\n");
626 spin_unlock(&rbu_data.lock);
627 return -EINVAL;
628 }
541 629
542 /* we must free all previous allocations */ 630 /* we must free all previous allocations */
543 packet_empty_list(); 631 packet_empty_list();
544 img_update_free(); 632 img_update_free();
545
546 spin_unlock(&rbu_data.lock); 633 spin_unlock(&rbu_data.lock);
547 return rc;
548 634
635 return rc;
549} 636}
550 637
551static struct bin_attribute rbu_data_attr = { 638static struct bin_attribute rbu_data_attr = {
@@ -559,51 +646,19 @@ static struct bin_attribute rbu_image_type_attr = {
559 .write = write_rbu_image_type, 646 .write = write_rbu_image_type,
560}; 647};
561 648
562static void callbackfn_rbu(const struct firmware *fw, void *context) 649static int __init
563{ 650dcdrbu_init(void)
564 int rc = 0;
565
566 if (!fw || !fw->size)
567 return;
568
569 spin_lock(&rbu_data.lock);
570 if (!strcmp(image_type, "mono")) {
571 if (!img_update_realloc(fw->size))
572 memcpy(rbu_data.image_update_buffer,
573 fw->data, fw->size);
574 } else if (!strcmp(image_type, "packet")) {
575 if (!rbu_data.packetsize)
576 rbu_data.packetsize = fw->size;
577 else if (rbu_data.packetsize != fw->size) {
578 packet_empty_list();
579 rbu_data.packetsize = fw->size;
580 }
581 packetize_data(fw->data, fw->size);
582 } else
583 pr_debug("invalid image type specified.\n");
584 spin_unlock(&rbu_data.lock);
585
586 rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
587 "dell_rbu", &rbu_device->dev,
588 &context, callbackfn_rbu);
589 if (rc)
590 printk(KERN_ERR
591 "dell_rbu:%s request_firmware_nowait failed"
592 " %d\n", __FUNCTION__, rc);
593}
594
595static int __init dcdrbu_init(void)
596{ 651{
597 int rc = 0; 652 int rc = 0;
598 spin_lock_init(&rbu_data.lock); 653 spin_lock_init(&rbu_data.lock);
599 654
600 init_packet_head(); 655 init_packet_head();
601 rbu_device = 656 rbu_device =
602 platform_device_register_simple("dell_rbu", -1, NULL, 0); 657 platform_device_register_simple("dell_rbu", -1, NULL, 0);
603 if (!rbu_device) { 658 if (!rbu_device) {
604 printk(KERN_ERR 659 printk(KERN_ERR
605 "dell_rbu:%s:platform_device_register_simple " 660 "dell_rbu:%s:platform_device_register_simple "
606 "failed\n", __FUNCTION__); 661 "failed\n", __FUNCTION__);
607 return -EIO; 662 return -EIO;
608 } 663 }
609 664
@@ -611,17 +666,19 @@ static int __init dcdrbu_init(void)
611 sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); 666 sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
612 667
613 rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, 668 rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
614 "dell_rbu", &rbu_device->dev, 669 "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);
615 &context, callbackfn_rbu);
616 if (rc) 670 if (rc)
617 printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait" 671 printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait"
618 " failed %d\n", __FUNCTION__, rc); 672 " failed %d\n", __FUNCTION__, rc);
673 else
674 rbu_data.entry_created = 1;
619 675
620 return rc; 676 return rc;
621 677
622} 678}
623 679
624static __exit void dcdrbu_exit(void) 680static __exit void
681dcdrbu_exit(void)
625{ 682{
626 spin_lock(&rbu_data.lock); 683 spin_lock(&rbu_data.lock);
627 packet_empty_list(); 684 packet_empty_list();