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