aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
authorStuart Hayes <stuart.w.hayes@gmail.com>2018-09-26 17:50:19 -0400
committerAndy Shevchenko <andriy.shevchenko@linux.intel.com>2018-09-27 05:18:15 -0400
commitc48e2ffd717ca4a67b4938bb60d110b7eeed39c4 (patch)
treee10693c4b4ce9a6ed3c70190781f9956049bcb0e /drivers/firmware
parent12c956c4f32e08799de452abe1e1ec6021b1e41f (diff)
firmware: dell_rbu: Move dell_rbu to drivers/platform/x86
Move dell_rbu to the more appropriate directory drivers/platform/x86. Signed-off-by: Stuart Hayes <stuart.w.hayes@gmail.com> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/Kconfig12
-rw-r--r--drivers/firmware/Makefile1
-rw-r--r--drivers/firmware/dell_rbu.c753
3 files changed, 0 insertions, 766 deletions
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 6e83880046d7..02f39d20efce 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -145,18 +145,6 @@ config EFI_PCDP
145 See DIG64_HCDPv20_042804.pdf available from 145 See DIG64_HCDPv20_042804.pdf available from
146 <http://www.dig64.org/specifications/> 146 <http://www.dig64.org/specifications/>
147 147
148config DELL_RBU
149 tristate "BIOS update support for DELL systems via sysfs"
150 depends on X86
151 select FW_LOADER
152 select FW_LOADER_USER_HELPER
153 help
154 Say m if you want to have the option of updating the BIOS for your
155 DELL system. Note you need a Dell OpenManage or Dell Update package (DUP)
156 supporting application to communicate with the BIOS regarding the new
157 image for the image update to take effect.
158 See <file:Documentation/dell_rbu.txt> for more details on the driver.
159
160config DCDBAS 148config DCDBAS
161 tristate "Dell Systems Management Base Driver" 149 tristate "Dell Systems Management Base Driver"
162 depends on X86 150 depends on X86
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index e18a041cfc53..61887ba9df1d 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -11,7 +11,6 @@ obj-$(CONFIG_DMI) += dmi_scan.o
11obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o 11obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o
12obj-$(CONFIG_EDD) += edd.o 12obj-$(CONFIG_EDD) += edd.o
13obj-$(CONFIG_EFI_PCDP) += pcdp.o 13obj-$(CONFIG_EFI_PCDP) += pcdp.o
14obj-$(CONFIG_DELL_RBU) += dell_rbu.o
15obj-$(CONFIG_DCDBAS) += dcdbas.o 14obj-$(CONFIG_DCDBAS) += dcdbas.o
16obj-$(CONFIG_DMIID) += dmi-id.o 15obj-$(CONFIG_DMIID) += dmi-id.o
17obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o 16obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
deleted file mode 100644
index ccefa84f7305..000000000000
--- a/drivers/firmware/dell_rbu.c
+++ /dev/null
@@ -1,753 +0,0 @@
1/*
2 * dell_rbu.c
3 * Bios Update driver for Dell systems
4 * Author: Dell Inc
5 * Abhay Salunke <abhay_salunke@dell.com>
6 *
7 * Copyright (C) 2005 Dell Inc.
8 *
9 * Remote BIOS Update (rbu) driver is used for updating DELL BIOS by
10 * creating entries in the /sys file systems on Linux 2.6 and higher
11 * kernels. The driver supports two mechanism to update the BIOS namely
12 * contiguous and packetized. Both these methods still require having some
13 * application to set the CMOS bit indicating the BIOS to update itself
14 * after a reboot.
15 *
16 * Contiguous method:
17 * This driver writes the incoming data in a monolithic image by allocating
18 * contiguous physical pages large enough to accommodate the incoming BIOS
19 * image size.
20 *
21 * Packetized method:
22 * The driver writes the incoming packet image by allocating a new packet
23 * on every time the packet data is written. This driver requires an
24 * application to break the BIOS image in to fixed sized packet chunks.
25 *
26 * See Documentation/dell_rbu.txt for more info.
27 *
28 * This program is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License v2.0 as published by
30 * the Free Software Foundation
31 *
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
36 */
37#include <linux/init.h>
38#include <linux/module.h>
39#include <linux/slab.h>
40#include <linux/string.h>
41#include <linux/errno.h>
42#include <linux/blkdev.h>
43#include <linux/platform_device.h>
44#include <linux/spinlock.h>
45#include <linux/moduleparam.h>
46#include <linux/firmware.h>
47#include <linux/dma-mapping.h>
48#include <asm/set_memory.h>
49
50MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
51MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
52MODULE_LICENSE("GPL");
53MODULE_VERSION("3.2");
54
55#define BIOS_SCAN_LIMIT 0xffffffff
56#define MAX_IMAGE_LENGTH 16
57static struct _rbu_data {
58 void *image_update_buffer;
59 unsigned long image_update_buffer_size;
60 unsigned long bios_image_size;
61 int image_update_ordernum;
62 int dma_alloc;
63 spinlock_t lock;
64 unsigned long packet_read_count;
65 unsigned long num_packets;
66 unsigned long packetsize;
67 unsigned long imagesize;
68 int entry_created;
69} rbu_data;
70
71static char image_type[MAX_IMAGE_LENGTH + 1] = "mono";
72module_param_string(image_type, image_type, sizeof (image_type), 0);
73MODULE_PARM_DESC(image_type,
74 "BIOS image type. choose- mono or packet or init");
75
76static unsigned long allocation_floor = 0x100000;
77module_param(allocation_floor, ulong, 0644);
78MODULE_PARM_DESC(allocation_floor,
79 "Minimum address for allocations when using Packet mode");
80
81struct packet_data {
82 struct list_head list;
83 size_t length;
84 void *data;
85 int ordernum;
86};
87
88static struct packet_data packet_data_head;
89
90static struct platform_device *rbu_device;
91static int context;
92static dma_addr_t dell_rbu_dmaaddr;
93
94static void init_packet_head(void)
95{
96 INIT_LIST_HEAD(&packet_data_head.list);
97 rbu_data.packet_read_count = 0;
98 rbu_data.num_packets = 0;
99 rbu_data.packetsize = 0;
100 rbu_data.imagesize = 0;
101}
102
103static int create_packet(void *data, size_t length)
104{
105 struct packet_data *newpacket;
106 int ordernum = 0;
107 int retval = 0;
108 unsigned int packet_array_size = 0;
109 void **invalid_addr_packet_array = NULL;
110 void *packet_data_temp_buf = NULL;
111 unsigned int idx = 0;
112
113 pr_debug("create_packet: entry \n");
114
115 if (!rbu_data.packetsize) {
116 pr_debug("create_packet: packetsize not specified\n");
117 retval = -EINVAL;
118 goto out_noalloc;
119 }
120
121 spin_unlock(&rbu_data.lock);
122
123 newpacket = kzalloc(sizeof (struct packet_data), GFP_KERNEL);
124
125 if (!newpacket) {
126 printk(KERN_WARNING
127 "dell_rbu:%s: failed to allocate new "
128 "packet\n", __func__);
129 retval = -ENOMEM;
130 spin_lock(&rbu_data.lock);
131 goto out_noalloc;
132 }
133
134 ordernum = get_order(length);
135
136 /*
137 * BIOS errata mean we cannot allocate packets below 1MB or they will
138 * be overwritten by BIOS.
139 *
140 * array to temporarily hold packets
141 * that are below the allocation floor
142 *
143 * NOTE: very simplistic because we only need the floor to be at 1MB
144 * due to BIOS errata. This shouldn't be used for higher floors
145 * or you will run out of mem trying to allocate the array.
146 */
147 packet_array_size = max(
148 (unsigned int)(allocation_floor / rbu_data.packetsize),
149 (unsigned int)1);
150 invalid_addr_packet_array = kcalloc(packet_array_size, sizeof(void *),
151 GFP_KERNEL);
152
153 if (!invalid_addr_packet_array) {
154 printk(KERN_WARNING
155 "dell_rbu:%s: failed to allocate "
156 "invalid_addr_packet_array \n",
157 __func__);
158 retval = -ENOMEM;
159 spin_lock(&rbu_data.lock);
160 goto out_alloc_packet;
161 }
162
163 while (!packet_data_temp_buf) {
164 packet_data_temp_buf = (unsigned char *)
165 __get_free_pages(GFP_KERNEL, ordernum);
166 if (!packet_data_temp_buf) {
167 printk(KERN_WARNING
168 "dell_rbu:%s: failed to allocate new "
169 "packet\n", __func__);
170 retval = -ENOMEM;
171 spin_lock(&rbu_data.lock);
172 goto out_alloc_packet_array;
173 }
174
175 if ((unsigned long)virt_to_phys(packet_data_temp_buf)
176 < allocation_floor) {
177 pr_debug("packet 0x%lx below floor at 0x%lx.\n",
178 (unsigned long)virt_to_phys(
179 packet_data_temp_buf),
180 allocation_floor);
181 invalid_addr_packet_array[idx++] = packet_data_temp_buf;
182 packet_data_temp_buf = NULL;
183 }
184 }
185 /*
186 * set to uncachable or it may never get written back before reboot
187 */
188 set_memory_uc((unsigned long)packet_data_temp_buf, 1 << ordernum);
189
190 spin_lock(&rbu_data.lock);
191
192 newpacket->data = packet_data_temp_buf;
193
194 pr_debug("create_packet: newpacket at physical addr %lx\n",
195 (unsigned long)virt_to_phys(newpacket->data));
196
197 /* packets may not have fixed size */
198 newpacket->length = length;
199 newpacket->ordernum = ordernum;
200 ++rbu_data.num_packets;
201
202 /* initialize the newly created packet headers */
203 INIT_LIST_HEAD(&newpacket->list);
204 list_add_tail(&newpacket->list, &packet_data_head.list);
205
206 memcpy(newpacket->data, data, length);
207
208 pr_debug("create_packet: exit \n");
209
210out_alloc_packet_array:
211 /* always free packet array */
212 for (;idx>0;idx--) {
213 pr_debug("freeing unused packet below floor 0x%lx.\n",
214 (unsigned long)virt_to_phys(
215 invalid_addr_packet_array[idx-1]));
216 free_pages((unsigned long)invalid_addr_packet_array[idx-1],
217 ordernum);
218 }
219 kfree(invalid_addr_packet_array);
220
221out_alloc_packet:
222 /* if error, free data */
223 if (retval)
224 kfree(newpacket);
225
226out_noalloc:
227 return retval;
228}
229
230static int packetize_data(const u8 *data, size_t length)
231{
232 int rc = 0;
233 int done = 0;
234 int packet_length;
235 u8 *temp;
236 u8 *end = (u8 *) data + length;
237 pr_debug("packetize_data: data length %zd\n", length);
238 if (!rbu_data.packetsize) {
239 printk(KERN_WARNING
240 "dell_rbu: packetsize not specified\n");
241 return -EIO;
242 }
243
244 temp = (u8 *) data;
245
246 /* packetize the hunk */
247 while (!done) {
248 if ((temp + rbu_data.packetsize) < end)
249 packet_length = rbu_data.packetsize;
250 else {
251 /* this is the last packet */
252 packet_length = end - temp;
253 done = 1;
254 }
255
256 if ((rc = create_packet(temp, packet_length)))
257 return rc;
258
259 pr_debug("%p:%td\n", temp, (end - temp));
260 temp += packet_length;
261 }
262
263 rbu_data.imagesize = length;
264
265 return rc;
266}
267
268static int do_packet_read(char *data, struct list_head *ptemp_list,
269 int length, int bytes_read, int *list_read_count)
270{
271 void *ptemp_buf;
272 struct packet_data *newpacket = NULL;
273 int bytes_copied = 0;
274 int j = 0;
275
276 newpacket = list_entry(ptemp_list, struct packet_data, list);
277 *list_read_count += newpacket->length;
278
279 if (*list_read_count > bytes_read) {
280 /* point to the start of unread data */
281 j = newpacket->length - (*list_read_count - bytes_read);
282 /* point to the offset in the packet buffer */
283 ptemp_buf = (u8 *) newpacket->data + j;
284 /*
285 * check if there is enough room in
286 * * the incoming buffer
287 */
288 if (length > (*list_read_count - bytes_read))
289 /*
290 * copy what ever is there in this
291 * packet and move on
292 */
293 bytes_copied = (*list_read_count - bytes_read);
294 else
295 /* copy the remaining */
296 bytes_copied = length;
297 memcpy(data, ptemp_buf, bytes_copied);
298 }
299 return bytes_copied;
300}
301
302static int packet_read_list(char *data, size_t * pread_length)
303{
304 struct list_head *ptemp_list;
305 int temp_count = 0;
306 int bytes_copied = 0;
307 int bytes_read = 0;
308 int remaining_bytes = 0;
309 char *pdest = data;
310
311 /* check if we have any packets */
312 if (0 == rbu_data.num_packets)
313 return -ENOMEM;
314
315 remaining_bytes = *pread_length;
316 bytes_read = rbu_data.packet_read_count;
317
318 ptemp_list = (&packet_data_head.list)->next;
319 while (!list_empty(ptemp_list)) {
320 bytes_copied = do_packet_read(pdest, ptemp_list,
321 remaining_bytes, bytes_read, &temp_count);
322 remaining_bytes -= bytes_copied;
323 bytes_read += bytes_copied;
324 pdest += bytes_copied;
325 /*
326 * check if we reached end of buffer before reaching the
327 * last packet
328 */
329 if (remaining_bytes == 0)
330 break;
331
332 ptemp_list = ptemp_list->next;
333 }
334 /*finally set the bytes read */
335 *pread_length = bytes_read - rbu_data.packet_read_count;
336 rbu_data.packet_read_count = bytes_read;
337 return 0;
338}
339
340static void packet_empty_list(void)
341{
342 struct list_head *ptemp_list;
343 struct list_head *pnext_list;
344 struct packet_data *newpacket;
345
346 ptemp_list = (&packet_data_head.list)->next;
347 while (!list_empty(ptemp_list)) {
348 newpacket =
349 list_entry(ptemp_list, struct packet_data, list);
350 pnext_list = ptemp_list->next;
351 list_del(ptemp_list);
352 ptemp_list = pnext_list;
353 /*
354 * zero out the RBU packet memory before freeing
355 * to make sure there are no stale RBU packets left in memory
356 */
357 memset(newpacket->data, 0, rbu_data.packetsize);
358 set_memory_wb((unsigned long)newpacket->data,
359 1 << newpacket->ordernum);
360 free_pages((unsigned long) newpacket->data,
361 newpacket->ordernum);
362 kfree(newpacket);
363 }
364 rbu_data.packet_read_count = 0;
365 rbu_data.num_packets = 0;
366 rbu_data.imagesize = 0;
367}
368
369/*
370 * img_update_free: Frees the buffer allocated for storing BIOS image
371 * Always called with lock held and returned with lock held
372 */
373static void img_update_free(void)
374{
375 if (!rbu_data.image_update_buffer)
376 return;
377 /*
378 * zero out this buffer before freeing it to get rid of any stale
379 * BIOS image copied in memory.
380 */
381 memset(rbu_data.image_update_buffer, 0,
382 rbu_data.image_update_buffer_size);
383 if (rbu_data.dma_alloc == 1)
384 dma_free_coherent(NULL, rbu_data.bios_image_size,
385 rbu_data.image_update_buffer, dell_rbu_dmaaddr);
386 else
387 free_pages((unsigned long) rbu_data.image_update_buffer,
388 rbu_data.image_update_ordernum);
389
390 /*
391 * Re-initialize the rbu_data variables after a free
392 */
393 rbu_data.image_update_ordernum = -1;
394 rbu_data.image_update_buffer = NULL;
395 rbu_data.image_update_buffer_size = 0;
396 rbu_data.bios_image_size = 0;
397 rbu_data.dma_alloc = 0;
398}
399
400/*
401 * img_update_realloc: This function allocates the contiguous pages to
402 * accommodate the requested size of data. The memory address and size
403 * values are stored globally and on every call to this function the new
404 * size is checked to see if more data is required than the existing size.
405 * If true the previous memory is freed and new allocation is done to
406 * accommodate the new size. If the incoming size is less then than the
407 * already allocated size, then that memory is reused. This function is
408 * called with lock held and returns with lock held.
409 */
410static int img_update_realloc(unsigned long size)
411{
412 unsigned char *image_update_buffer = NULL;
413 unsigned long rc;
414 unsigned long img_buf_phys_addr;
415 int ordernum;
416 int dma_alloc = 0;
417
418 /*
419 * check if the buffer of sufficient size has been
420 * already allocated
421 */
422 if (rbu_data.image_update_buffer_size >= size) {
423 /*
424 * check for corruption
425 */
426 if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
427 printk(KERN_ERR "dell_rbu:%s: corruption "
428 "check failed\n", __func__);
429 return -EINVAL;
430 }
431 /*
432 * we have a valid pre-allocated buffer with
433 * sufficient size
434 */
435 return 0;
436 }
437
438 /*
439 * free any previously allocated buffer
440 */
441 img_update_free();
442
443 spin_unlock(&rbu_data.lock);
444
445 ordernum = get_order(size);
446 image_update_buffer =
447 (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum);
448
449 img_buf_phys_addr =
450 (unsigned long) virt_to_phys(image_update_buffer);
451
452 if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {
453 free_pages((unsigned long) image_update_buffer, ordernum);
454 ordernum = -1;
455 image_update_buffer = dma_alloc_coherent(NULL, size,
456 &dell_rbu_dmaaddr, GFP_KERNEL);
457 dma_alloc = 1;
458 }
459
460 spin_lock(&rbu_data.lock);
461
462 if (image_update_buffer != NULL) {
463 rbu_data.image_update_buffer = image_update_buffer;
464 rbu_data.image_update_buffer_size = size;
465 rbu_data.bios_image_size =
466 rbu_data.image_update_buffer_size;
467 rbu_data.image_update_ordernum = ordernum;
468 rbu_data.dma_alloc = dma_alloc;
469 rc = 0;
470 } else {
471 pr_debug("Not enough memory for image update:"
472 "size = %ld\n", size);
473 rc = -ENOMEM;
474 }
475
476 return rc;
477}
478
479static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
480{
481 int retval;
482 size_t bytes_left;
483 size_t data_length;
484 char *ptempBuf = buffer;
485
486 /* check to see if we have something to return */
487 if (rbu_data.num_packets == 0) {
488 pr_debug("read_packet_data: no packets written\n");
489 retval = -ENOMEM;
490 goto read_rbu_data_exit;
491 }
492
493 if (pos > rbu_data.imagesize) {
494 retval = 0;
495 printk(KERN_WARNING "dell_rbu:read_packet_data: "
496 "data underrun\n");
497 goto read_rbu_data_exit;
498 }
499
500 bytes_left = rbu_data.imagesize - pos;
501 data_length = min(bytes_left, count);
502
503 if ((retval = packet_read_list(ptempBuf, &data_length)) < 0)
504 goto read_rbu_data_exit;
505
506 if ((pos + count) > rbu_data.imagesize) {
507 rbu_data.packet_read_count = 0;
508 /* this was the last copy */
509 retval = bytes_left;
510 } else
511 retval = count;
512
513 read_rbu_data_exit:
514 return retval;
515}
516
517static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
518{
519 /* check to see if we have something to return */
520 if ((rbu_data.image_update_buffer == NULL) ||
521 (rbu_data.bios_image_size == 0)) {
522 pr_debug("read_rbu_data_mono: image_update_buffer %p ,"
523 "bios_image_size %lu\n",
524 rbu_data.image_update_buffer,
525 rbu_data.bios_image_size);
526 return -ENOMEM;
527 }
528
529 return memory_read_from_buffer(buffer, count, &pos,
530 rbu_data.image_update_buffer, rbu_data.bios_image_size);
531}
532
533static ssize_t read_rbu_data(struct file *filp, struct kobject *kobj,
534 struct bin_attribute *bin_attr,
535 char *buffer, loff_t pos, size_t count)
536{
537 ssize_t ret_count = 0;
538
539 spin_lock(&rbu_data.lock);
540
541 if (!strcmp(image_type, "mono"))
542 ret_count = read_rbu_mono_data(buffer, pos, count);
543 else if (!strcmp(image_type, "packet"))
544 ret_count = read_packet_data(buffer, pos, count);
545 else
546 pr_debug("read_rbu_data: invalid image type specified\n");
547
548 spin_unlock(&rbu_data.lock);
549 return ret_count;
550}
551
552static void callbackfn_rbu(const struct firmware *fw, void *context)
553{
554 rbu_data.entry_created = 0;
555
556 if (!fw)
557 return;
558
559 if (!fw->size)
560 goto out;
561
562 spin_lock(&rbu_data.lock);
563 if (!strcmp(image_type, "mono")) {
564 if (!img_update_realloc(fw->size))
565 memcpy(rbu_data.image_update_buffer,
566 fw->data, fw->size);
567 } else if (!strcmp(image_type, "packet")) {
568 /*
569 * we need to free previous packets if a
570 * new hunk of packets needs to be downloaded
571 */
572 packet_empty_list();
573 if (packetize_data(fw->data, fw->size))
574 /* Incase something goes wrong when we are
575 * in middle of packetizing the data, we
576 * need to free up whatever packets might
577 * have been created before we quit.
578 */
579 packet_empty_list();
580 } else
581 pr_debug("invalid image type specified.\n");
582 spin_unlock(&rbu_data.lock);
583 out:
584 release_firmware(fw);
585}
586
587static ssize_t read_rbu_image_type(struct file *filp, struct kobject *kobj,
588 struct bin_attribute *bin_attr,
589 char *buffer, loff_t pos, size_t count)
590{
591 int size = 0;
592 if (!pos)
593 size = scnprintf(buffer, count, "%s\n", image_type);
594 return size;
595}
596
597static ssize_t write_rbu_image_type(struct file *filp, struct kobject *kobj,
598 struct bin_attribute *bin_attr,
599 char *buffer, loff_t pos, size_t count)
600{
601 int rc = count;
602 int req_firm_rc = 0;
603 int i;
604 spin_lock(&rbu_data.lock);
605 /*
606 * Find the first newline or space
607 */
608 for (i = 0; i < count; ++i)
609 if (buffer[i] == '\n' || buffer[i] == ' ') {
610 buffer[i] = '\0';
611 break;
612 }
613 if (i == count)
614 buffer[count] = '\0';
615
616 if (strstr(buffer, "mono"))
617 strcpy(image_type, "mono");
618 else if (strstr(buffer, "packet"))
619 strcpy(image_type, "packet");
620 else if (strstr(buffer, "init")) {
621 /*
622 * If due to the user error the driver gets in a bad
623 * state where even though it is loaded , the
624 * /sys/class/firmware/dell_rbu entries are missing.
625 * to cover this situation the user can recreate entries
626 * by writing init to image_type.
627 */
628 if (!rbu_data.entry_created) {
629 spin_unlock(&rbu_data.lock);
630 req_firm_rc = request_firmware_nowait(THIS_MODULE,
631 FW_ACTION_NOHOTPLUG, "dell_rbu",
632 &rbu_device->dev, GFP_KERNEL, &context,
633 callbackfn_rbu);
634 if (req_firm_rc) {
635 printk(KERN_ERR
636 "dell_rbu:%s request_firmware_nowait"
637 " failed %d\n", __func__, rc);
638 rc = -EIO;
639 } else
640 rbu_data.entry_created = 1;
641
642 spin_lock(&rbu_data.lock);
643 }
644 } else {
645 printk(KERN_WARNING "dell_rbu: image_type is invalid\n");
646 spin_unlock(&rbu_data.lock);
647 return -EINVAL;
648 }
649
650 /* we must free all previous allocations */
651 packet_empty_list();
652 img_update_free();
653 spin_unlock(&rbu_data.lock);
654
655 return rc;
656}
657
658static ssize_t read_rbu_packet_size(struct file *filp, struct kobject *kobj,
659 struct bin_attribute *bin_attr,
660 char *buffer, loff_t pos, size_t count)
661{
662 int size = 0;
663 if (!pos) {
664 spin_lock(&rbu_data.lock);
665 size = scnprintf(buffer, count, "%lu\n", rbu_data.packetsize);
666 spin_unlock(&rbu_data.lock);
667 }
668 return size;
669}
670
671static ssize_t write_rbu_packet_size(struct file *filp, struct kobject *kobj,
672 struct bin_attribute *bin_attr,
673 char *buffer, loff_t pos, size_t count)
674{
675 unsigned long temp;
676 spin_lock(&rbu_data.lock);
677 packet_empty_list();
678 sscanf(buffer, "%lu", &temp);
679 if (temp < 0xffffffff)
680 rbu_data.packetsize = temp;
681
682 spin_unlock(&rbu_data.lock);
683 return count;
684}
685
686static struct bin_attribute rbu_data_attr = {
687 .attr = {.name = "data", .mode = 0444},
688 .read = read_rbu_data,
689};
690
691static struct bin_attribute rbu_image_type_attr = {
692 .attr = {.name = "image_type", .mode = 0644},
693 .read = read_rbu_image_type,
694 .write = write_rbu_image_type,
695};
696
697static struct bin_attribute rbu_packet_size_attr = {
698 .attr = {.name = "packet_size", .mode = 0644},
699 .read = read_rbu_packet_size,
700 .write = write_rbu_packet_size,
701};
702
703static int __init dcdrbu_init(void)
704{
705 int rc;
706 spin_lock_init(&rbu_data.lock);
707
708 init_packet_head();
709 rbu_device = platform_device_register_simple("dell_rbu", -1, NULL, 0);
710 if (IS_ERR(rbu_device)) {
711 printk(KERN_ERR
712 "dell_rbu:%s:platform_device_register_simple "
713 "failed\n", __func__);
714 return PTR_ERR(rbu_device);
715 }
716
717 rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
718 if (rc)
719 goto out_devreg;
720 rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
721 if (rc)
722 goto out_data;
723 rc = sysfs_create_bin_file(&rbu_device->dev.kobj,
724 &rbu_packet_size_attr);
725 if (rc)
726 goto out_imtype;
727
728 rbu_data.entry_created = 0;
729 return 0;
730
731out_imtype:
732 sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
733out_data:
734 sysfs_remove_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
735out_devreg:
736 platform_device_unregister(rbu_device);
737 return rc;
738}
739
740static __exit void dcdrbu_exit(void)
741{
742 spin_lock(&rbu_data.lock);
743 packet_empty_list();
744 img_update_free();
745 spin_unlock(&rbu_data.lock);
746 platform_device_unregister(rbu_device);
747}
748
749module_exit(dcdrbu_exit);
750module_init(dcdrbu_init);
751
752/* vim:noet:ts=8:sw=8
753*/