diff options
Diffstat (limited to 'drivers/firmware/dell_rbu.c')
| -rw-r--r-- | drivers/firmware/dell_rbu.c | 241 |
1 files changed, 145 insertions, 96 deletions
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index 3b865f34a095..b66782398258 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c | |||
| @@ -50,7 +50,7 @@ | |||
| 50 | MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); | 50 | MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); |
| 51 | MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); | 51 | MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); |
| 52 | MODULE_LICENSE("GPL"); | 52 | MODULE_LICENSE("GPL"); |
| 53 | MODULE_VERSION("1.0"); | 53 | MODULE_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 | ||
| 70 | static char image_type[MAX_IMAGE_LENGTH] = "mono"; | 71 | static char image_type[MAX_IMAGE_LENGTH + 1] = "mono"; |
| 71 | module_param_string(image_type, image_type, sizeof(image_type), 0); | 72 | module_param_string(image_type, image_type, sizeof (image_type), 0); |
| 72 | MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet"); | 73 | MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet"); |
| 73 | 74 | ||
| 74 | struct packet_data { | 75 | struct packet_data { |
| @@ -114,7 +115,7 @@ static int fill_last_packet(void *data, size_t length) | |||
| 114 | 115 | ||
| 115 | if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) { | 116 | if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) { |
| 116 | pr_debug("dell_rbu:%s: packet size data " | 117 | pr_debug("dell_rbu:%s: packet size data " |
| 117 | "overrun\n", __FUNCTION__); | 118 | "overrun\n", __FUNCTION__); |
| 118 | return -EINVAL; | 119 | return -EINVAL; |
| 119 | } | 120 | } |
| 120 | 121 | ||
| @@ -146,12 +147,14 @@ static int create_packet(size_t length) | |||
| 146 | pr_debug("create_packet: packetsize not specified\n"); | 147 | pr_debug("create_packet: packetsize not specified\n"); |
| 147 | return -EINVAL; | 148 | return -EINVAL; |
| 148 | } | 149 | } |
| 150 | spin_unlock(&rbu_data.lock); | ||
| 151 | newpacket = kmalloc(sizeof (struct packet_data), GFP_KERNEL); | ||
| 152 | spin_lock(&rbu_data.lock); | ||
| 149 | 153 | ||
| 150 | newpacket = kmalloc(sizeof(struct packet_data), GFP_KERNEL); | ||
| 151 | if (!newpacket) { | 154 | if (!newpacket) { |
| 152 | printk(KERN_WARNING | 155 | printk(KERN_WARNING |
| 153 | "dell_rbu:%s: failed to allocate new " | 156 | "dell_rbu:%s: failed to allocate new " |
| 154 | "packet\n", __FUNCTION__); | 157 | "packet\n", __FUNCTION__); |
| 155 | return -ENOMEM; | 158 | return -ENOMEM; |
| 156 | } | 159 | } |
| 157 | 160 | ||
| @@ -160,15 +163,17 @@ static int create_packet(size_t length) | |||
| 160 | * there is no upper limit on memory | 163 | * there is no upper limit on memory |
| 161 | * address for packetized mechanism | 164 | * address for packetized mechanism |
| 162 | */ | 165 | */ |
| 163 | newpacket->data = (unsigned char *)__get_free_pages(GFP_KERNEL, | 166 | spin_unlock(&rbu_data.lock); |
| 164 | ordernum); | 167 | newpacket->data = (unsigned char *) __get_free_pages(GFP_KERNEL, |
| 168 | ordernum); | ||
| 169 | spin_lock(&rbu_data.lock); | ||
| 165 | 170 | ||
| 166 | pr_debug("create_packet: newpacket %p\n", newpacket->data); | 171 | pr_debug("create_packet: newpacket %p\n", newpacket->data); |
| 167 | 172 | ||
| 168 | if (!newpacket->data) { | 173 | if (!newpacket->data) { |
| 169 | printk(KERN_WARNING | 174 | printk(KERN_WARNING |
| 170 | "dell_rbu:%s: failed to allocate new " | 175 | "dell_rbu:%s: failed to allocate new " |
| 171 | "packet\n", __FUNCTION__); | 176 | "packet\n", __FUNCTION__); |
| 172 | kfree(newpacket); | 177 | kfree(newpacket); |
| 173 | return -ENOMEM; | 178 | return -ENOMEM; |
| 174 | } | 179 | } |
| @@ -204,9 +209,8 @@ static int packetize_data(void *data, size_t length) | |||
| 204 | return rc; | 209 | return rc; |
| 205 | } | 210 | } |
| 206 | 211 | ||
| 207 | static int | 212 | static int do_packet_read(char *data, struct list_head *ptemp_list, |
| 208 | do_packet_read(char *data, struct list_head *ptemp_list, | 213 | int length, int bytes_read, int *list_read_count) |
| 209 | int length, int bytes_read, int *list_read_count) | ||
| 210 | { | 214 | { |
| 211 | void *ptemp_buf; | 215 | void *ptemp_buf; |
| 212 | struct packet_data *newpacket = NULL; | 216 | struct packet_data *newpacket = NULL; |
| @@ -239,7 +243,7 @@ do_packet_read(char *data, struct list_head *ptemp_list, | |||
| 239 | return bytes_copied; | 243 | return bytes_copied; |
| 240 | } | 244 | } |
| 241 | 245 | ||
| 242 | static int packet_read_list(char *data, size_t * pread_length) | 246 | static int packet_read_list(char *data, size_t *pread_length) |
| 243 | { | 247 | { |
| 244 | struct list_head *ptemp_list; | 248 | struct list_head *ptemp_list; |
| 245 | int temp_count = 0; | 249 | int temp_count = 0; |
| @@ -258,8 +262,7 @@ static int packet_read_list(char *data, size_t * pread_length) | |||
| 258 | ptemp_list = (&packet_data_head.list)->next; | 262 | ptemp_list = (&packet_data_head.list)->next; |
| 259 | while (!list_empty(ptemp_list)) { | 263 | while (!list_empty(ptemp_list)) { |
| 260 | bytes_copied = do_packet_read(pdest, ptemp_list, | 264 | bytes_copied = do_packet_read(pdest, ptemp_list, |
| 261 | remaining_bytes, bytes_read, | 265 | remaining_bytes, bytes_read, &temp_count); |
| 262 | &temp_count); | ||
| 263 | remaining_bytes -= bytes_copied; | 266 | remaining_bytes -= bytes_copied; |
| 264 | bytes_read += bytes_copied; | 267 | bytes_read += bytes_copied; |
| 265 | pdest += bytes_copied; | 268 | pdest += bytes_copied; |
| @@ -287,7 +290,7 @@ static void packet_empty_list(void) | |||
| 287 | ptemp_list = (&packet_data_head.list)->next; | 290 | ptemp_list = (&packet_data_head.list)->next; |
| 288 | while (!list_empty(ptemp_list)) { | 291 | while (!list_empty(ptemp_list)) { |
| 289 | newpacket = | 292 | newpacket = |
| 290 | list_entry(ptemp_list, struct packet_data, list); | 293 | list_entry(ptemp_list, struct packet_data, list); |
| 291 | pnext_list = ptemp_list->next; | 294 | pnext_list = ptemp_list->next; |
| 292 | list_del(ptemp_list); | 295 | list_del(ptemp_list); |
| 293 | ptemp_list = pnext_list; | 296 | ptemp_list = pnext_list; |
| @@ -296,8 +299,8 @@ static void packet_empty_list(void) | |||
| 296 | * to make sure there are no stale RBU packets left in memory | 299 | * to make sure there are no stale RBU packets left in memory |
| 297 | */ | 300 | */ |
| 298 | memset(newpacket->data, 0, rbu_data.packetsize); | 301 | memset(newpacket->data, 0, rbu_data.packetsize); |
| 299 | free_pages((unsigned long)newpacket->data, | 302 | free_pages((unsigned long) newpacket->data, |
| 300 | newpacket->ordernum); | 303 | newpacket->ordernum); |
| 301 | kfree(newpacket); | 304 | kfree(newpacket); |
| 302 | } | 305 | } |
| 303 | rbu_data.packet_write_count = 0; | 306 | rbu_data.packet_write_count = 0; |
| @@ -319,14 +322,13 @@ static void img_update_free(void) | |||
| 319 | * BIOS image copied in memory. | 322 | * BIOS image copied in memory. |
| 320 | */ | 323 | */ |
| 321 | memset(rbu_data.image_update_buffer, 0, | 324 | memset(rbu_data.image_update_buffer, 0, |
| 322 | rbu_data.image_update_buffer_size); | 325 | rbu_data.image_update_buffer_size); |
| 323 | if (rbu_data.dma_alloc == 1) | 326 | if (rbu_data.dma_alloc == 1) |
| 324 | dma_free_coherent(NULL, rbu_data.bios_image_size, | 327 | dma_free_coherent(NULL, rbu_data.bios_image_size, |
| 325 | rbu_data.image_update_buffer, | 328 | rbu_data.image_update_buffer, dell_rbu_dmaaddr); |
| 326 | dell_rbu_dmaaddr); | ||
| 327 | else | 329 | else |
| 328 | free_pages((unsigned long)rbu_data.image_update_buffer, | 330 | free_pages((unsigned long) rbu_data.image_update_buffer, |
| 329 | rbu_data.image_update_ordernum); | 331 | rbu_data.image_update_ordernum); |
| 330 | 332 | ||
| 331 | /* | 333 | /* |
| 332 | * Re-initialize the rbu_data variables after a free | 334 | * Re-initialize the rbu_data variables after a free |
| @@ -366,7 +368,7 @@ static int img_update_realloc(unsigned long size) | |||
| 366 | */ | 368 | */ |
| 367 | if ((size != 0) && (rbu_data.image_update_buffer == NULL)) { | 369 | if ((size != 0) && (rbu_data.image_update_buffer == NULL)) { |
| 368 | printk(KERN_ERR "dell_rbu:%s: corruption " | 370 | printk(KERN_ERR "dell_rbu:%s: corruption " |
| 369 | "check failed\n", __FUNCTION__); | 371 | "check failed\n", __FUNCTION__); |
| 370 | return -EINVAL; | 372 | return -EINVAL; |
| 371 | } | 373 | } |
| 372 | /* | 374 | /* |
| @@ -385,17 +387,16 @@ static int img_update_realloc(unsigned long size) | |||
| 385 | 387 | ||
| 386 | ordernum = get_order(size); | 388 | ordernum = get_order(size); |
| 387 | image_update_buffer = | 389 | image_update_buffer = |
| 388 | (unsigned char *)__get_free_pages(GFP_KERNEL, ordernum); | 390 | (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum); |
| 389 | 391 | ||
| 390 | img_buf_phys_addr = | 392 | img_buf_phys_addr = |
| 391 | (unsigned long)virt_to_phys(image_update_buffer); | 393 | (unsigned long) virt_to_phys(image_update_buffer); |
| 392 | 394 | ||
| 393 | if (img_buf_phys_addr > BIOS_SCAN_LIMIT) { | 395 | if (img_buf_phys_addr > BIOS_SCAN_LIMIT) { |
| 394 | free_pages((unsigned long)image_update_buffer, ordernum); | 396 | free_pages((unsigned long) image_update_buffer, ordernum); |
| 395 | ordernum = -1; | 397 | ordernum = -1; |
| 396 | image_update_buffer = dma_alloc_coherent(NULL, size, | 398 | image_update_buffer = dma_alloc_coherent(NULL, size, |
| 397 | &dell_rbu_dmaaddr, | 399 | &dell_rbu_dmaaddr, GFP_KERNEL); |
| 398 | GFP_KERNEL); | ||
| 399 | dma_alloc = 1; | 400 | dma_alloc = 1; |
| 400 | } | 401 | } |
| 401 | 402 | ||
| @@ -405,13 +406,13 @@ static int img_update_realloc(unsigned long size) | |||
| 405 | rbu_data.image_update_buffer = image_update_buffer; | 406 | rbu_data.image_update_buffer = image_update_buffer; |
| 406 | rbu_data.image_update_buffer_size = size; | 407 | rbu_data.image_update_buffer_size = size; |
| 407 | rbu_data.bios_image_size = | 408 | rbu_data.bios_image_size = |
| 408 | rbu_data.image_update_buffer_size; | 409 | rbu_data.image_update_buffer_size; |
| 409 | rbu_data.image_update_ordernum = ordernum; | 410 | rbu_data.image_update_ordernum = ordernum; |
| 410 | rbu_data.dma_alloc = dma_alloc; | 411 | rbu_data.dma_alloc = dma_alloc; |
| 411 | rc = 0; | 412 | rc = 0; |
| 412 | } else { | 413 | } else { |
| 413 | pr_debug("Not enough memory for image update:" | 414 | pr_debug("Not enough memory for image update:" |
| 414 | "size = %ld\n", size); | 415 | "size = %ld\n", size); |
| 415 | rc = -ENOMEM; | 416 | rc = -ENOMEM; |
| 416 | } | 417 | } |
| 417 | 418 | ||
| @@ -438,7 +439,7 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) | |||
| 438 | if (pos > imagesize) { | 439 | if (pos > imagesize) { |
| 439 | retval = 0; | 440 | retval = 0; |
| 440 | printk(KERN_WARNING "dell_rbu:read_packet_data: " | 441 | printk(KERN_WARNING "dell_rbu:read_packet_data: " |
| 441 | "data underrun\n"); | 442 | "data underrun\n"); |
| 442 | goto read_rbu_data_exit; | 443 | goto read_rbu_data_exit; |
| 443 | } | 444 | } |
| 444 | 445 | ||
| @@ -468,11 +469,11 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) | |||
| 468 | 469 | ||
| 469 | /* check to see if we have something to return */ | 470 | /* check to see if we have something to return */ |
| 470 | if ((rbu_data.image_update_buffer == NULL) || | 471 | if ((rbu_data.image_update_buffer == NULL) || |
| 471 | (rbu_data.bios_image_size == 0)) { | 472 | (rbu_data.bios_image_size == 0)) { |
| 472 | pr_debug("read_rbu_data_mono: image_update_buffer %p ," | 473 | pr_debug("read_rbu_data_mono: image_update_buffer %p ," |
| 473 | "bios_image_size %lu\n", | 474 | "bios_image_size %lu\n", |
| 474 | rbu_data.image_update_buffer, | 475 | rbu_data.image_update_buffer, |
| 475 | rbu_data.bios_image_size); | 476 | rbu_data.bios_image_size); |
| 476 | ret_count = -ENOMEM; | 477 | ret_count = -ENOMEM; |
| 477 | goto read_rbu_data_exit; | 478 | goto read_rbu_data_exit; |
| 478 | } | 479 | } |
| @@ -497,8 +498,8 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) | |||
| 497 | return ret_count; | 498 | return ret_count; |
| 498 | } | 499 | } |
| 499 | 500 | ||
| 500 | static ssize_t | 501 | static ssize_t read_rbu_data(struct kobject *kobj, char *buffer, |
| 501 | read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count) | 502 | loff_t pos, size_t count) |
| 502 | { | 503 | { |
| 503 | ssize_t ret_count = 0; | 504 | ssize_t ret_count = 0; |
| 504 | 505 | ||
| @@ -515,62 +516,20 @@ read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count) | |||
| 515 | return ret_count; | 516 | return ret_count; |
| 516 | } | 517 | } |
| 517 | 518 | ||
| 518 | static ssize_t | ||
| 519 | read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, | ||
| 520 | size_t count) | ||
| 521 | { | ||
| 522 | int size = 0; | ||
| 523 | if (!pos) | ||
| 524 | size = sprintf(buffer, "%s\n", image_type); | ||
| 525 | return size; | ||
| 526 | } | ||
| 527 | |||
| 528 | static ssize_t | ||
| 529 | write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, | ||
| 530 | size_t count) | ||
| 531 | { | ||
| 532 | int rc = count; | ||
| 533 | spin_lock(&rbu_data.lock); | ||
| 534 | |||
| 535 | if (strlen(buffer) < MAX_IMAGE_LENGTH) | ||
| 536 | sscanf(buffer, "%s", image_type); | ||
| 537 | else | ||
| 538 | printk(KERN_WARNING "dell_rbu: image_type is invalid" | ||
| 539 | "max chars = %d, \n incoming str--%s-- \n", | ||
| 540 | MAX_IMAGE_LENGTH, buffer); | ||
| 541 | |||
| 542 | /* we must free all previous allocations */ | ||
| 543 | packet_empty_list(); | ||
| 544 | img_update_free(); | ||
| 545 | |||
| 546 | spin_unlock(&rbu_data.lock); | ||
| 547 | return rc; | ||
| 548 | |||
| 549 | } | ||
| 550 | |||
| 551 | static struct bin_attribute rbu_data_attr = { | ||
| 552 | .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444}, | ||
| 553 | .read = read_rbu_data, | ||
| 554 | }; | ||
| 555 | |||
| 556 | static struct bin_attribute rbu_image_type_attr = { | ||
| 557 | .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644}, | ||
| 558 | .read = read_rbu_image_type, | ||
| 559 | .write = write_rbu_image_type, | ||
| 560 | }; | ||
| 561 | |||
| 562 | static void callbackfn_rbu(const struct firmware *fw, void *context) | 519 | static void callbackfn_rbu(const struct firmware *fw, void *context) |
| 563 | { | 520 | { |
| 564 | int rc = 0; | 521 | int rc = 0; |
| 565 | 522 | ||
| 566 | if (!fw || !fw->size) | 523 | if (!fw || !fw->size) { |
| 524 | rbu_data.entry_created = 0; | ||
| 567 | return; | 525 | return; |
| 526 | } | ||
| 568 | 527 | ||
| 569 | spin_lock(&rbu_data.lock); | 528 | spin_lock(&rbu_data.lock); |
| 570 | if (!strcmp(image_type, "mono")) { | 529 | if (!strcmp(image_type, "mono")) { |
| 571 | if (!img_update_realloc(fw->size)) | 530 | if (!img_update_realloc(fw->size)) |
| 572 | memcpy(rbu_data.image_update_buffer, | 531 | memcpy(rbu_data.image_update_buffer, |
| 573 | fw->data, fw->size); | 532 | fw->data, fw->size); |
| 574 | } else if (!strcmp(image_type, "packet")) { | 533 | } else if (!strcmp(image_type, "packet")) { |
| 575 | if (!rbu_data.packetsize) | 534 | if (!rbu_data.packetsize) |
| 576 | rbu_data.packetsize = fw->size; | 535 | rbu_data.packetsize = fw->size; |
| @@ -584,14 +543,103 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) | |||
| 584 | spin_unlock(&rbu_data.lock); | 543 | spin_unlock(&rbu_data.lock); |
| 585 | 544 | ||
| 586 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | 545 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, |
| 587 | "dell_rbu", &rbu_device->dev, | 546 | "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); |
| 588 | &context, callbackfn_rbu); | ||
| 589 | if (rc) | 547 | if (rc) |
| 590 | printk(KERN_ERR | 548 | printk(KERN_ERR |
| 591 | "dell_rbu:%s request_firmware_nowait failed" | 549 | "dell_rbu:%s request_firmware_nowait failed" |
| 592 | " %d\n", __FUNCTION__, rc); | 550 | " %d\n", __FUNCTION__, rc); |
| 551 | else | ||
| 552 | rbu_data.entry_created = 1; | ||
| 553 | } | ||
| 554 | |||
| 555 | static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, | ||
| 556 | loff_t pos, size_t count) | ||
| 557 | { | ||
| 558 | int size = 0; | ||
| 559 | if (!pos) | ||
| 560 | size = sprintf(buffer, "%s\n", image_type); | ||
| 561 | return size; | ||
| 562 | } | ||
| 563 | |||
| 564 | static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer, | ||
| 565 | loff_t pos, size_t count) | ||
| 566 | { | ||
| 567 | int rc = count; | ||
| 568 | int req_firm_rc = 0; | ||
| 569 | int i; | ||
| 570 | spin_lock(&rbu_data.lock); | ||
| 571 | /* | ||
| 572 | * Find the first newline or space | ||
| 573 | */ | ||
| 574 | for (i = 0; i < count; ++i) | ||
| 575 | if (buffer[i] == '\n' || buffer[i] == ' ') { | ||
| 576 | buffer[i] = '\0'; | ||
| 577 | break; | ||
| 578 | } | ||
| 579 | if (i == count) | ||
| 580 | buffer[count] = '\0'; | ||
| 581 | |||
| 582 | if (strstr(buffer, "mono")) | ||
| 583 | strcpy(image_type, "mono"); | ||
| 584 | else if (strstr(buffer, "packet")) | ||
| 585 | strcpy(image_type, "packet"); | ||
| 586 | else if (strstr(buffer, "init")) { | ||
| 587 | /* | ||
| 588 | * If due to the user error the driver gets in a bad | ||
| 589 | * state where even though it is loaded , the | ||
| 590 | * /sys/class/firmware/dell_rbu entries are missing. | ||
| 591 | * to cover this situation the user can recreate entries | ||
| 592 | * by writing init to image_type. | ||
| 593 | */ | ||
| 594 | if (!rbu_data.entry_created) { | ||
| 595 | spin_unlock(&rbu_data.lock); | ||
| 596 | req_firm_rc = request_firmware_nowait(THIS_MODULE, | ||
| 597 | FW_ACTION_NOHOTPLUG, "dell_rbu", | ||
| 598 | &rbu_device->dev, &context, | ||
| 599 | callbackfn_rbu); | ||
| 600 | if (req_firm_rc) { | ||
| 601 | printk(KERN_ERR | ||
| 602 | "dell_rbu:%s request_firmware_nowait" | ||
| 603 | " failed %d\n", __FUNCTION__, rc); | ||
| 604 | rc = -EIO; | ||
| 605 | } else | ||
| 606 | rbu_data.entry_created = 1; | ||
| 607 | |||
| 608 | spin_lock(&rbu_data.lock); | ||
| 609 | } | ||
| 610 | } else { | ||
| 611 | printk(KERN_WARNING "dell_rbu: image_type is invalid\n"); | ||
| 612 | spin_unlock(&rbu_data.lock); | ||
| 613 | return -EINVAL; | ||
| 614 | } | ||
| 615 | |||
| 616 | /* we must free all previous allocations */ | ||
| 617 | packet_empty_list(); | ||
| 618 | img_update_free(); | ||
| 619 | spin_unlock(&rbu_data.lock); | ||
| 620 | |||
| 621 | return rc; | ||
| 593 | } | 622 | } |
| 594 | 623 | ||
| 624 | static struct bin_attribute rbu_data_attr = { | ||
| 625 | .attr = { | ||
| 626 | .name = "data", | ||
| 627 | .owner = THIS_MODULE, | ||
| 628 | .mode = 0444, | ||
| 629 | }, | ||
| 630 | .read = read_rbu_data, | ||
| 631 | }; | ||
| 632 | |||
| 633 | static struct bin_attribute rbu_image_type_attr = { | ||
| 634 | .attr = { | ||
| 635 | .name = "image_type", | ||
| 636 | .owner = THIS_MODULE, | ||
| 637 | .mode = 0644, | ||
| 638 | }, | ||
| 639 | .read = read_rbu_image_type, | ||
| 640 | .write = write_rbu_image_type, | ||
| 641 | }; | ||
| 642 | |||
| 595 | static int __init dcdrbu_init(void) | 643 | static int __init dcdrbu_init(void) |
| 596 | { | 644 | { |
| 597 | int rc = 0; | 645 | int rc = 0; |
| @@ -599,11 +647,11 @@ static int __init dcdrbu_init(void) | |||
| 599 | 647 | ||
| 600 | init_packet_head(); | 648 | init_packet_head(); |
| 601 | rbu_device = | 649 | rbu_device = |
| 602 | platform_device_register_simple("dell_rbu", -1, NULL, 0); | 650 | platform_device_register_simple("dell_rbu", -1, NULL, 0); |
| 603 | if (!rbu_device) { | 651 | if (!rbu_device) { |
| 604 | printk(KERN_ERR | 652 | printk(KERN_ERR |
| 605 | "dell_rbu:%s:platform_device_register_simple " | 653 | "dell_rbu:%s:platform_device_register_simple " |
| 606 | "failed\n", __FUNCTION__); | 654 | "failed\n", __FUNCTION__); |
| 607 | return -EIO; | 655 | return -EIO; |
| 608 | } | 656 | } |
| 609 | 657 | ||
| @@ -611,11 +659,12 @@ static int __init dcdrbu_init(void) | |||
| 611 | sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); | 659 | sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); |
| 612 | 660 | ||
| 613 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | 661 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, |
| 614 | "dell_rbu", &rbu_device->dev, | 662 | "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); |
| 615 | &context, callbackfn_rbu); | ||
| 616 | if (rc) | 663 | if (rc) |
| 617 | printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait" | 664 | printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait" |
| 618 | " failed %d\n", __FUNCTION__, rc); | 665 | " failed %d\n", __FUNCTION__, rc); |
| 666 | else | ||
| 667 | rbu_data.entry_created = 1; | ||
| 619 | 668 | ||
| 620 | return rc; | 669 | return rc; |
| 621 | 670 | ||
