static ssize_t write_rbu_image_type(struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer, loff_t pos, size_t count) { int rc = count; int req_firm_rc = 0; int i; spin_lock(&rbu_data.lock); /* * Find the first newline or space */ for (i = 0; i < count; ++i) if (buffer[i] == '\n' || buffer[i] == ' ') { buffer[i] = '\0'; break; } if (i == count) buffer[count] = '\0'; if (strstr(buffer, "mono")) strcpy(image_type, "mono"); else if (strstr(buffer, "packet")) strcpy(image_type, "packet"); else if (strstr(buffer, "init")) { /* * If due to the user error the driver gets in a bad * state where even though it is loaded , the * /sys/class/firmware/dell_rbu entries are missing. * to cover this situation the user can recreate entries * by writing init to image_type. */ if (!rbu_data.entry_created) { spin_unlock(&rbu_data.lock); req_firm_rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); if (req_firm_rc) { printk(KERN_ERR "dell_rbu:%s request_firmware_nowait" " failed %d\n", __func__, rc); rc = -EIO; } else rbu_data.entry_created = 1; spin_lock(&rbu_data.lock); } } else { printk(KERN_WARNING "dell_rbu: image_type is invalid\n"); spin_unlock(&rbu_data.lock); return -EINVAL; } /* we must free all previous allocations */ packet_empty_list(); img_update_free(); spin_unlock(&rbu_data.lock); return rc; }
static __exit void dcdrbu_exit(void) { spin_lock(&rbu_data.lock); packet_empty_list(); img_update_free(); spin_unlock(&rbu_data.lock); platform_device_unregister(rbu_device); }
/* * img_update_realloc: This function allocates the contiguous pages to * accommodate the requested size of data. The memory address and size * values are stored globally and on every call to this function the new * size is checked to see if more data is required than the existing size. * If true the previous memory is freed and new allocation is done to * accommodate the new size. If the incoming size is less then than the * already allocated size, then that memory is reused. This function is * called with lock held and returns with lock held. */ static int img_update_realloc(unsigned long size) { unsigned char *image_update_buffer = NULL; unsigned long rc; #ifndef CONFIG_XEN unsigned long img_buf_phys_addr; #endif int ordernum; int dma_alloc = 0; /* * check if the buffer of sufficient size has been * already allocated */ if (rbu_data.image_update_buffer_size >= size) { /* * check for corruption */ if ((size != 0) && (rbu_data.image_update_buffer == NULL)) { printk(KERN_ERR "dell_rbu:%s: corruption " "check failed\n", __func__); return -EINVAL; } /* * we have a valid pre-allocated buffer with * sufficient size */ return 0; } /* * free any previously allocated buffer */ img_update_free(); spin_unlock(&rbu_data.lock); #ifndef CONFIG_XEN ordernum = get_order(size); image_update_buffer = (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum); img_buf_phys_addr = (unsigned long) virt_to_bus(image_update_buffer); if (img_buf_phys_addr > BIOS_SCAN_LIMIT) { free_pages((unsigned long) image_update_buffer, ordernum); #else { #endif ordernum = -1; image_update_buffer = dma_alloc_coherent(NULL, size, &dell_rbu_dmaaddr, GFP_KERNEL); dma_alloc = 1; } spin_lock(&rbu_data.lock); if (image_update_buffer != NULL) { rbu_data.image_update_buffer = image_update_buffer; rbu_data.image_update_buffer_size = size; rbu_data.bios_image_size = rbu_data.image_update_buffer_size; rbu_data.image_update_ordernum = ordernum; rbu_data.dma_alloc = dma_alloc; rc = 0; } else { pr_debug("Not enough memory for image update:" "size = %ld\n", size); rc = -ENOMEM; } return rc; } static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) { int retval; size_t bytes_left; size_t data_length; char *ptempBuf = buffer; /* check to see if we have something to return */ if (rbu_data.num_packets == 0) { pr_debug("read_packet_data: no packets written\n"); retval = -ENOMEM; goto read_rbu_data_exit; } if (pos > rbu_data.imagesize) { retval = 0; printk(KERN_WARNING "dell_rbu:read_packet_data: " "data underrun\n"); goto read_rbu_data_exit; } bytes_left = rbu_data.imagesize - pos; data_length = min(bytes_left, count); if ((retval = packet_read_list(ptempBuf, &data_length)) < 0) goto read_rbu_data_exit; if ((pos + count) > rbu_data.imagesize) { rbu_data.packet_read_count = 0; /* this was the last copy */ retval = bytes_left; } else retval = count; read_rbu_data_exit: return retval; }
/* * img_update_realloc: This function allocates the contiguous pages to * accommodate the requested size of data. The memory address and size * values are stored globally and on every call to this function the new * size is checked to see if more data is required than the existing size. * If true the previous memory is freed and new allocation is done to * accommodate the new size. If the incoming size is less then than the * already allocated size, then that memory is reused. This function is * called with lock held and returns with lock held. */ static int img_update_realloc(unsigned long size) { unsigned char *image_update_buffer = NULL; unsigned long rc; unsigned long img_buf_phys_addr; int ordernum; int dma_alloc = 0; /* * check if the buffer of sufficient size has been * already allocated */ if (rbu_data.image_update_buffer_size >= size) { /* * check for corruption */ if ((size != 0) && (rbu_data.image_update_buffer == NULL)) { printk(KERN_ERR "dell_rbu:%s: corruption " "check failed\n", __func__); return -EINVAL; } /* * we have a valid pre-allocated buffer with * sufficient size */ return 0; } /* * free any previously allocated buffer */ img_update_free(); spin_unlock(&rbu_data.lock); ordernum = get_order(size); image_update_buffer = (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum); img_buf_phys_addr = (unsigned long) virt_to_phys(image_update_buffer); if (img_buf_phys_addr > BIOS_SCAN_LIMIT) { free_pages((unsigned long) image_update_buffer, ordernum); ordernum = -1; image_update_buffer = dma_alloc_coherent(NULL, size, &dell_rbu_dmaaddr, GFP_KERNEL); dma_alloc = 1; } spin_lock(&rbu_data.lock); if (image_update_buffer != NULL) { rbu_data.image_update_buffer = image_update_buffer; rbu_data.image_update_buffer_size = size; rbu_data.bios_image_size = rbu_data.image_update_buffer_size; rbu_data.image_update_ordernum = ordernum; rbu_data.dma_alloc = dma_alloc; rc = 0; } else { pr_debug("Not enough memory for image update:" "size = %ld\n", size); rc = -ENOMEM; } return rc; }