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