1. Replace file I/O of reading firmware by request_firmware(). 2. Coding style clean up. Signed-off-by: Macpaul Lin <macpaul@xxxxxxxxx> Cc: Paul Stewart <pstew@xxxxxxxxxxxx> Cc: Ben Chan <benchan@xxxxxxxxxxxx> Cc: Sage Ahn <syahn@xxxxxxxxxxx> Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/staging/gdm72xx/usb_boot.c | 207 ++++++++++++++++++------------------- 1 file changed, 99 insertions(+), 108 deletions(-) diff --git a/drivers/staging/gdm72xx/usb_boot.c b/drivers/staging/gdm72xx/usb_boot.c index e3dbd5a..e1cd017 100644 --- a/drivers/staging/gdm72xx/usb_boot.c +++ b/drivers/staging/gdm72xx/usb_boot.c @@ -18,25 +18,29 @@ #include <linux/usb.h> #include <linux/unistd.h> #include <linux/slab.h> +#include <linux/firmware.h> #include <asm/byteorder.h> #include "gdm_usb.h" #include "usb_boot.h" -#define DN_KERNEL_MAGIC_NUMBER 0x10760001 -#define DN_ROOTFS_MAGIC_NUMBER 0x10760002 +#define DN_KERNEL_MAGIC_NUMBER 0x10760001 +#define DN_ROOTFS_MAGIC_NUMBER 0x10760002 -#define DOWNLOAD_SIZE 1024 +#define DOWNLOAD_SIZE 1024 -#define DH2B(x) __cpu_to_be32(x) -#define DL2H(x) __le32_to_cpu(x) +#define DH2B(x) __cpu_to_be32(x) +#define DL2H(x) __le32_to_cpu(x) -#define MIN(a, b) ((a) > (b) ? (b) : (a)) +#define MIN(a, b) ((a) > (b) ? (b) : (a)) #define MAX_IMG_CNT 16 -#define UIMG_PATH "/lib/firmware/gdm72xx/gdmuimg.bin" -#define KERN_PATH "/lib/firmware/gdm72xx/zImage" -#define FS_PATH "/lib/firmware/gdm72xx/ramdisk.jffs2" + +#define FW_DIR "gdm72xx/" + +#define FW_UIMG "gdmuimg.bin" +#define FW_KERN "zImage" +#define FW_FS "ramdisk.jffs2" struct dn_header { u32 magic_num; @@ -44,23 +48,23 @@ struct dn_header { }; struct img_header { - u32 magic_code; - u32 count; - u32 len; - u32 offset[MAX_IMG_CNT]; + u32 magic_code; + u32 count; + u32 len; + u32 offset[MAX_IMG_CNT]; char hostname[32]; char date[32]; }; struct fw_info { - u32 id; - u32 len; - u32 kernel_len; - u32 rootfs_len; - u32 kernel_offset; - u32 rootfs_offset; - u32 fw_ver; - u32 mac_ver; + u32 id; + u32 len; + u32 kernel_len; + u32 rootfs_len; + u32 kernel_offset; + u32 rootfs_offset; + u32 fw_ver; + u32 mac_ver; char hostname[32]; char userid[16]; char date[32]; @@ -107,13 +111,13 @@ static int gdm_wibro_recv(struct usb_device *usbdev, void *data, int len) return 0; } -static int download_image(struct usb_device *usbdev, struct file *filp, - loff_t *pos, u32 img_len, u32 magic_num) +static int download_image(struct usb_device *usbdev, + const struct firmware *firm, + loff_t pos, u32 img_len, u32 magic_num) { struct dn_header h; int ret = 0; u32 size; - int len, readn; size = (img_len + DOWNLOAD_SIZE - 1) & ~(DOWNLOAD_SIZE - 1); h.magic_num = DH2B(magic_num); @@ -123,43 +127,43 @@ static int download_image(struct usb_device *usbdev, struct file *filp, if (ret < 0) goto out; - readn = 0; - while ((len = filp->f_op->read(filp, tx_buf, DOWNLOAD_SIZE, pos))) { - - if (len < 0) { - ret = -1; + while (img_len > 0) { + if (img_len > DOWNLOAD_SIZE) { + memcpy(tx_buf, firm->data + pos, DOWNLOAD_SIZE); + ret = gdm_wibro_send(usbdev, tx_buf, DOWNLOAD_SIZE); + } else { /* the last chuch of data */ + memcpy(tx_buf, firm->data + pos, img_len); + ret = gdm_wibro_send(usbdev, tx_buf, img_len); goto out; } - readn += len; - ret = gdm_wibro_send(usbdev, tx_buf, DOWNLOAD_SIZE); + img_len -= DOWNLOAD_SIZE; + pos += DOWNLOAD_SIZE; + if (ret < 0) goto out; - if (readn >= img_len) - break; } - if (readn < img_len) { - printk(KERN_ERR "gdmwm: Cannot read to the requested size. " - "Read = %d Requested = %d\n", readn, img_len); - ret = -EIO; - } out: - return ret; } int usb_boot(struct usb_device *usbdev, u16 pid) { int i, ret = 0; - struct file *filp = NULL; - struct inode *inode = NULL; - static mm_segment_t fs; struct img_header hdr; struct fw_info fw_info; loff_t pos = 0; - char *img_name = UIMG_PATH; - int len; + char *img_name = FW_DIR FW_UIMG; + const struct firmware *firm; + + ret = request_firmware(&firm, img_name, &usbdev->dev); + if (ret < 0) { + printk(KERN_ERR + "requesting firmware %s failed with error %d\n", + img_name, ret); + return ret; + } tx_buf = kmalloc(DOWNLOAD_SIZE, GFP_KERNEL); if (tx_buf == NULL) { @@ -167,29 +171,12 @@ int usb_boot(struct usb_device *usbdev, u16 pid) return -ENOMEM; } - fs = get_fs(); - set_fs(get_ds()); - - filp = filp_open(img_name, O_RDONLY | O_LARGEFILE, 0); - if (IS_ERR(filp)) { - printk(KERN_ERR "Can't find %s.\n", img_name); - ret = PTR_ERR(filp); - goto restore_fs; - } - - inode = filp->f_dentry->d_inode; - if (!S_ISREG(inode->i_mode)) { - printk(KERN_ERR "Invalid file type: %s\n", img_name); - ret = -EINVAL; - goto out; - } - - len = filp->f_op->read(filp, (u8 *)&hdr, sizeof(hdr), &pos); - if (len != sizeof(hdr)) { + if (firm->size < sizeof(hdr)) { printk(KERN_ERR "gdmwm: Cannot read the image info.\n"); ret = -EIO; goto out; } + memcpy((u8 *)&hdr, firm->data, sizeof(hdr)); array_le32_to_cpu((u32 *)&hdr, 19); #if 0 @@ -217,13 +204,12 @@ int usb_boot(struct usb_device *usbdev, u16 pid) } pos = hdr.offset[i]; - len = filp->f_op->read(filp, (u8 *)&fw_info, sizeof(fw_info), - &pos); - if (len != sizeof(fw_info)) { + if (firm->size < sizeof(fw_info) + pos) { printk(KERN_ERR "gdmwm: Cannot read the FW info.\n"); ret = -EIO; goto out; } + memcpy((u8 *)&fw_info, firm->data + pos, sizeof(fw_info)); array_le32_to_cpu((u32 *)&fw_info, 8); #if 0 @@ -239,14 +225,23 @@ int usb_boot(struct usb_device *usbdev, u16 pid) continue; pos = hdr.offset[i] + fw_info.kernel_offset; - ret = download_image(usbdev, filp, &pos, fw_info.kernel_len, - DN_KERNEL_MAGIC_NUMBER); + if (firm->size < fw_info.kernel_len + pos) { + printk(KERN_ERR "gdmwm: Kernel FW is too small.\n"); + goto out; + } + + ret = download_image(usbdev, firm, pos, + fw_info.kernel_len, DN_KERNEL_MAGIC_NUMBER); if (ret < 0) goto out; printk(KERN_INFO "GCT: Kernel download success.\n"); pos = hdr.offset[i] + fw_info.rootfs_offset; - ret = download_image(usbdev, filp, &pos, fw_info.rootfs_len, + if (firm->size < fw_info.rootfs_len + pos) { + printk(KERN_ERR "gdmwm: Filesystem FW is too small.\n"); + goto out; + } + ret = download_image(usbdev, firm, pos, fw_info.rootfs_len, DN_ROOTFS_MAGIC_NUMBER); if (ret < 0) goto out; @@ -260,10 +255,8 @@ int usb_boot(struct usb_device *usbdev, u16 pid) ret = -EINVAL; } out: - filp_close(filp, NULL); - -restore_fs: - set_fs(fs); + release_firmware(firm); + firm = NULL; kfree(tx_buf); return ret; } @@ -293,38 +286,27 @@ out: return ret; } -static int em_download_image(struct usb_device *usbdev, char *path, +static int em_download_image(struct usb_device *usbdev, char *img_name, char *type_string) { - struct file *filp; - struct inode *inode; - static mm_segment_t fs; char *buf = NULL; loff_t pos = 0; int ret = 0; - int len, readn = 0; + int len = 0; + int img_len = 0; + const struct firmware *firm; #if defined(GDM7205_PADDING) const int pad_size = GDM7205_PADDING; #else const int pad_size = 0; #endif - fs = get_fs(); - set_fs(get_ds()); - - filp = filp_open(path, O_RDONLY | O_LARGEFILE, 0); - if (IS_ERR(filp)) { - printk(KERN_ERR "Can't find %s.\n", path); - set_fs(fs); - ret = -ENOENT; - goto restore_fs; - } - - inode = filp->f_dentry->d_inode; - if (!S_ISREG(inode->i_mode)) { - printk(KERN_ERR "Invalid file type: %s\n", path); - ret = -EINVAL; - goto out; + ret = request_firmware(&firm, img_name, &usbdev->dev); + if (ret < 0) { + printk(KERN_ERR + "requesting firmware %s failed with error %d\n", + img_name, ret); + return ret; } buf = kmalloc(DOWNLOAD_CHUCK + pad_size, GFP_KERNEL); @@ -338,15 +320,25 @@ static int em_download_image(struct usb_device *usbdev, char *path, if (ret < 0) goto out; - while ((len = filp->f_op->read(filp, buf+pad_size, DOWNLOAD_CHUCK, - &pos))) { - if (len < 0) { - ret = -1; - goto out; + img_len = firm->size; + + if (img_len <= 0) { + ret = -1; + goto out; + } + + while (img_len > 0) { + if (img_len > DOWNLOAD_CHUCK) { + memcpy(buf+pad_size, firm->data + pos, DOWNLOAD_CHUCK); + ret = gdm_wibro_send(usbdev, buf, len+pad_size); + } else { /* the last chuch of data */ + memcpy(buf+pad_size, firm->data + pos, img_len); + ret = gdm_wibro_send(usbdev, buf, len+pad_size); } - readn += len; - ret = gdm_wibro_send(usbdev, buf, len+pad_size); + img_len -= DOWNLOAD_CHUCK; + pos += DOWNLOAD_CHUCK; + if (ret < 0) goto out; @@ -360,11 +352,8 @@ static int em_download_image(struct usb_device *usbdev, char *path, goto out; out: - filp_close(filp, NULL); - -restore_fs: - set_fs(fs); - + release_firmware(firm); + firm = NULL; kfree(buf); return ret; @@ -382,13 +371,15 @@ static int em_fw_reset(struct usb_device *usbdev) int usb_emergency(struct usb_device *usbdev) { int ret; + char *kern_name = FW_DIR FW_KERN; + char *fs_name = FW_DIR FW_FS; - ret = em_download_image(usbdev, KERN_PATH, KERNEL_TYPE_STRING); + ret = em_download_image(usbdev, kern_name, KERNEL_TYPE_STRING); if (ret < 0) goto out; printk(KERN_INFO "GCT Emergency: Kernel download success.\n"); - ret = em_download_image(usbdev, FS_PATH, FS_TYPE_STRING); + ret = em_download_image(usbdev, fs_name, FS_TYPE_STRING); if (ret < 0) goto out; printk(KERN_INFO "GCT Emergency: Filesystem download success.\n"); -- 1.7.11.2.138.g2b53359 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/devel