Skip to content

Commit ad6ce87

Browse files
Abhay SalunkeLinus Torvalds
Abhay Salunke
authored and
Linus Torvalds
committed
[PATCH] dell_rbu: changes in packet update mechanism
In the current dell_rbu code ver 2.0 the packet update mechanism makes the user app dump every individual packet in to the driver. This adds in efficiency as every packet update makes the /sys/class/firmware/dell_rbu/loading and data files to disappear and reappear again. Thus the user app needs to wait for the files to reappear to dump another packet. This slows down the packet update tremendously in case of large number of packets. I am submitting a new patch for dell_rbu which will change the way we do packet updates; In the new method the user app will create a new single file which has already packetized the rbu image and all the packets are now staged in this file. This driver also creates a new entry in /sys/devices/platform/dell_rbu/packet_size ; the user needs to echo the packet size here before downloading the packet file. The user should do the following: create one single file which has all the packets stacked together. echo the packet size in to /sys/devices/platform/dell_rbu/packet_size. echo 1 > /sys/class/firmware/dell_rbu/loading cat the packetfile > /sys/class/firmware/dell_rbu/data echo 0 > /sys/class/firmware/dell_rbu/loading The driver takes the file which came through /sys/class/firmware/dell_rbu/data and takes chunks of paket_size data from it and place in contiguous memory. This makes packet update process very efficient and fast. As all the packet update happens in one single operation. The user can still read back the downloaded file from /sys/devices/platform/dell_rbu/data. 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>
1 parent e4314bf commit ad6ce87

File tree

2 files changed

+121
-91
lines changed

2 files changed

+121
-91
lines changed

Documentation/dell_rbu.txt

+28-10
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ The driver load creates the following directories under the /sys file system.
3535
/sys/class/firmware/dell_rbu/data
3636
/sys/devices/platform/dell_rbu/image_type
3737
/sys/devices/platform/dell_rbu/data
38+
/sys/devices/platform/dell_rbu/packet_size
3839

3940
The driver supports two types of update mechanism; monolithic and packetized.
4041
These update mechanism depends upon the BIOS currently running on the system.
@@ -47,8 +48,26 @@ By default the driver uses monolithic memory for the update type. This can be
4748
changed to packets during the driver load time by specifying the load
4849
parameter image_type=packet. This can also be changed later as below
4950
echo packet > /sys/devices/platform/dell_rbu/image_type
50-
Also echoing either mono ,packet or init in to image_type will free up the
51-
memory allocated by the driver.
51+
52+
In packet update mode the packet size has to be given before any packets can
53+
be downloaded. It is done as below
54+
echo XXXX > /sys/devices/platform/dell_rbu/packet_size
55+
In the packet update mechanism, the user neesd to create a new file having
56+
packets of data arranged back to back. It can be done as follows
57+
The user creates packets header, gets the chunk of the BIOS image and
58+
placs it next to the packetheader; now, the packetheader + BIOS image chunk
59+
added to geather should match the specified packet_size. This makes one
60+
packet, the user needs to create more such packets out of the entire BIOS
61+
image file and then arrange all these packets back to back in to one single
62+
file.
63+
This file is then copied to /sys/class/firmware/dell_rbu/data.
64+
Once this file gets to the driver, the driver extracts packet_size data from
65+
the file and spreads it accross the physical memory in contiguous packet_sized
66+
space.
67+
This method makes sure that all the packets get to the driver in a single operation.
68+
69+
In monolithic update the user simply get the BIOS image (.hdr file) and copies
70+
to the data file as is without any change to the BIOS image itself.
5271

5372
Do the steps below to download the BIOS image.
5473
1) echo 1 > /sys/class/firmware/dell_rbu/loading
@@ -58,23 +77,22 @@ Do the steps below to download the BIOS image.
5877
The /sys/class/firmware/dell_rbu/ entries will remain till the following is
5978
done.
6079
echo -1 > /sys/class/firmware/dell_rbu/loading.
61-
Until this step is completed the drivr cannot be unloaded.
80+
Until this step is completed the driver cannot be unloaded.
81+
Also echoing either mono ,packet or init in to image_type will free up the
82+
memory allocated by the driver.
83+
6284
If an user by accident executes steps 1 and 3 above without executing step 2;
6385
it will make the /sys/class/firmware/dell_rbu/ entries to disappear.
6486
The entries can be recreated by doing the following
6587
echo init > /sys/devices/platform/dell_rbu/image_type
6688
NOTE: echoing init in image_type does not change it original value.
6789

6890
Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to
69-
read back the image downloaded. This is useful in case of packet update
70-
mechanism where the above steps 1,2,3 will repeated for every packet.
71-
By reading the /sys/devices/platform/dell_rbu/data file all packet data
72-
downloaded can be verified in a single file.
73-
The packets are arranged in this file one after the other in a FIFO order.
91+
read back the image downloaded.
7492

7593
NOTE:
76-
This driver requires a patch for firmware_class.c which has the addition
77-
of request_firmware_nowait_nohotplug function to wortk
94+
This driver requires a patch for firmware_class.c which has the modified
95+
request_firmware_nowait function.
7896
Also after updating the BIOS image an user mdoe application neeeds to execute
7997
code which message the BIOS update request to the BIOS. So on the next reboot
8098
the BIOS knows about the new image downloaded and it updates it self.

drivers/firmware/dell_rbu.c

+93-81
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
5151
MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
5252
MODULE_LICENSE("GPL");
53-
MODULE_VERSION("2.0");
53+
MODULE_VERSION("3.0");
5454

5555
#define BIOS_SCAN_LIMIT 0xffffffff
5656
#define MAX_IMAGE_LENGTH 16
@@ -62,15 +62,16 @@ static struct _rbu_data {
6262
int dma_alloc;
6363
spinlock_t lock;
6464
unsigned long packet_read_count;
65-
unsigned long packet_write_count;
6665
unsigned long num_packets;
6766
unsigned long packetsize;
67+
unsigned long imagesize;
6868
int entry_created;
6969
} rbu_data;
7070

7171
static char image_type[MAX_IMAGE_LENGTH + 1] = "mono";
7272
module_param_string(image_type, image_type, sizeof (image_type), 0);
73-
MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet");
73+
MODULE_PARM_DESC(image_type,
74+
"BIOS image type. choose- mono or packet or init");
7475

7576
struct packet_data {
7677
struct list_head list;
@@ -88,55 +89,13 @@ static dma_addr_t dell_rbu_dmaaddr;
8889
static void init_packet_head(void)
8990
{
9091
INIT_LIST_HEAD(&packet_data_head.list);
91-
rbu_data.packet_write_count = 0;
9292
rbu_data.packet_read_count = 0;
9393
rbu_data.num_packets = 0;
9494
rbu_data.packetsize = 0;
95+
rbu_data.imagesize = 0;
9596
}
9697

97-
static int fill_last_packet(void *data, size_t length)
98-
{
99-
struct list_head *ptemp_list;
100-
struct packet_data *packet = NULL;
101-
int packet_count = 0;
102-
103-
pr_debug("fill_last_packet: entry \n");
104-
105-
if (!rbu_data.num_packets) {
106-
pr_debug("fill_last_packet: num_packets=0\n");
107-
return -ENOMEM;
108-
}
109-
110-
packet_count = rbu_data.num_packets;
111-
112-
ptemp_list = (&packet_data_head.list)->prev;
113-
114-
packet = list_entry(ptemp_list, struct packet_data, list);
115-
116-
if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) {
117-
pr_debug("dell_rbu:%s: packet size data "
118-
"overrun\n", __FUNCTION__);
119-
return -EINVAL;
120-
}
121-
122-
pr_debug("fill_last_packet : buffer = %p\n", packet->data);
123-
124-
memcpy((packet->data + rbu_data.packet_write_count), data, length);
125-
126-
if ((rbu_data.packet_write_count + length) == rbu_data.packetsize) {
127-
/*
128-
* this was the last data chunk in the packet
129-
* so reinitialize the packet data counter to zero
130-
*/
131-
rbu_data.packet_write_count = 0;
132-
} else
133-
rbu_data.packet_write_count += length;
134-
135-
pr_debug("fill_last_packet: exit \n");
136-
return 0;
137-
}
138-
139-
static int create_packet(size_t length)
98+
static int create_packet(void *data, size_t length)
14099
{
141100
struct packet_data *newpacket;
142101
int ordernum = 0;
@@ -186,9 +145,11 @@ static int create_packet(size_t length)
186145
INIT_LIST_HEAD(&newpacket->list);
187146
list_add_tail(&newpacket->list, &packet_data_head.list);
188147
/*
189-
* packets have fixed size
148+
* packets may not have fixed size
190149
*/
191-
newpacket->length = rbu_data.packetsize;
150+
newpacket->length = length;
151+
152+
memcpy(newpacket->data, data, length);
192153

193154
pr_debug("create_packet: exit \n");
194155

@@ -198,13 +159,37 @@ static int create_packet(size_t length)
198159
static int packetize_data(void *data, size_t length)
199160
{
200161
int rc = 0;
162+
int done = 0;
163+
int packet_length;
164+
u8 *temp;
165+
u8 *end = (u8 *) data + length;
166+
pr_debug("packetize_data: data length %d\n", length);
167+
if (!rbu_data.packetsize) {
168+
printk(KERN_WARNING
169+
"dell_rbu: packetsize not specified\n");
170+
return -EIO;
171+
}
201172

202-
if (!rbu_data.packet_write_count) {
203-
if ((rc = create_packet(length)))
173+
temp = (u8 *) data;
174+
175+
/* packetize the hunk */
176+
while (!done) {
177+
if ((temp + rbu_data.packetsize) < end)
178+
packet_length = rbu_data.packetsize;
179+
else {
180+
/* this is the last packet */
181+
packet_length = end - temp;
182+
done = 1;
183+
}
184+
185+
if ((rc = create_packet(temp, packet_length)))
204186
return rc;
187+
188+
pr_debug("%lu:%lu\n", temp, (end - temp));
189+
temp += packet_length;
205190
}
206-
if ((rc = fill_last_packet(data, length)))
207-
return rc;
191+
192+
rbu_data.imagesize = length;
208193

209194
return rc;
210195
}
@@ -243,7 +228,7 @@ static int do_packet_read(char *data, struct list_head *ptemp_list,
243228
return bytes_copied;
244229
}
245230

246-
static int packet_read_list(char *data, size_t *pread_length)
231+
static int packet_read_list(char *data, size_t * pread_length)
247232
{
248233
struct list_head *ptemp_list;
249234
int temp_count = 0;
@@ -303,10 +288,9 @@ static void packet_empty_list(void)
303288
newpacket->ordernum);
304289
kfree(newpacket);
305290
}
306-
rbu_data.packet_write_count = 0;
307291
rbu_data.packet_read_count = 0;
308292
rbu_data.num_packets = 0;
309-
rbu_data.packetsize = 0;
293+
rbu_data.imagesize = 0;
310294
}
311295

312296
/*
@@ -425,7 +409,6 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
425409
size_t bytes_left;
426410
size_t data_length;
427411
char *ptempBuf = buffer;
428-
unsigned long imagesize;
429412

430413
/* check to see if we have something to return */
431414
if (rbu_data.num_packets == 0) {
@@ -434,22 +417,20 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
434417
goto read_rbu_data_exit;
435418
}
436419

437-
imagesize = rbu_data.num_packets * rbu_data.packetsize;
438-
439-
if (pos > imagesize) {
420+
if (pos > rbu_data.imagesize) {
440421
retval = 0;
441422
printk(KERN_WARNING "dell_rbu:read_packet_data: "
442423
"data underrun\n");
443424
goto read_rbu_data_exit;
444425
}
445426

446-
bytes_left = imagesize - pos;
427+
bytes_left = rbu_data.imagesize - pos;
447428
data_length = min(bytes_left, count);
448429

449430
if ((retval = packet_read_list(ptempBuf, &data_length)) < 0)
450431
goto read_rbu_data_exit;
451432

452-
if ((pos + count) > imagesize) {
433+
if ((pos + count) > rbu_data.imagesize) {
453434
rbu_data.packet_read_count = 0;
454435
/* this was the last copy */
455436
retval = bytes_left;
@@ -499,7 +480,7 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
499480
}
500481

501482
static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,
502-
loff_t pos, size_t count)
483+
loff_t pos, size_t count)
503484
{
504485
ssize_t ret_count = 0;
505486

@@ -531,13 +512,18 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
531512
memcpy(rbu_data.image_update_buffer,
532513
fw->data, fw->size);
533514
} else if (!strcmp(image_type, "packet")) {
534-
if (!rbu_data.packetsize)
535-
rbu_data.packetsize = fw->size;
536-
else if (rbu_data.packetsize != fw->size) {
515+
/*
516+
* we need to free previous packets if a
517+
* new hunk of packets needs to be downloaded
518+
*/
519+
packet_empty_list();
520+
if (packetize_data(fw->data, fw->size))
521+
/* Incase something goes wrong when we are
522+
* in middle of packetizing the data, we
523+
* need to free up whatever packets might
524+
* have been created before we quit.
525+
*/
537526
packet_empty_list();
538-
rbu_data.packetsize = fw->size;
539-
}
540-
packetize_data(fw->data, fw->size);
541527
} else
542528
pr_debug("invalid image type specified.\n");
543529
spin_unlock(&rbu_data.lock);
@@ -553,7 +539,7 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
553539
}
554540

555541
static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
556-
loff_t pos, size_t count)
542+
loff_t pos, size_t count)
557543
{
558544
int size = 0;
559545
if (!pos)
@@ -562,7 +548,7 @@ static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
562548
}
563549

564550
static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
565-
loff_t pos, size_t count)
551+
loff_t pos, size_t count)
566552
{
567553
int rc = count;
568554
int req_firm_rc = 0;
@@ -621,25 +607,49 @@ static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
621607
return rc;
622608
}
623609

610+
static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer,
611+
loff_t pos, size_t count)
612+
{
613+
int size = 0;
614+
if (!pos) {
615+
spin_lock(&rbu_data.lock);
616+
size = sprintf(buffer, "%lu\n", rbu_data.packetsize);
617+
spin_unlock(&rbu_data.lock);
618+
}
619+
return size;
620+
}
621+
622+
static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer,
623+
loff_t pos, size_t count)
624+
{
625+
unsigned long temp;
626+
spin_lock(&rbu_data.lock);
627+
packet_empty_list();
628+
sscanf(buffer, "%lu", &temp);
629+
if (temp < 0xffffffff)
630+
rbu_data.packetsize = temp;
631+
632+
spin_unlock(&rbu_data.lock);
633+
return count;
634+
}
635+
624636
static struct bin_attribute rbu_data_attr = {
625-
.attr = {
626-
.name = "data",
627-
.owner = THIS_MODULE,
628-
.mode = 0444,
629-
},
637+
.attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},
630638
.read = read_rbu_data,
631639
};
632640

633641
static struct bin_attribute rbu_image_type_attr = {
634-
.attr = {
635-
.name = "image_type",
636-
.owner = THIS_MODULE,
637-
.mode = 0644,
638-
},
642+
.attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},
639643
.read = read_rbu_image_type,
640644
.write = write_rbu_image_type,
641645
};
642646

647+
static struct bin_attribute rbu_packet_size_attr = {
648+
.attr = {.name = "packet_size",.owner = THIS_MODULE,.mode = 0644},
649+
.read = read_rbu_packet_size,
650+
.write = write_rbu_packet_size,
651+
};
652+
643653
static int __init dcdrbu_init(void)
644654
{
645655
int rc = 0;
@@ -657,6 +667,8 @@ static int __init dcdrbu_init(void)
657667

658668
sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr);
659669
sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
670+
sysfs_create_bin_file(&rbu_device->dev.kobj,
671+
&rbu_packet_size_attr);
660672

661673
rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
662674
"dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);

0 commit comments

Comments
 (0)