diff options
-rw-r--r-- | drivers/net/wireless/at76c50x-usb.c | 87 |
1 files changed, 56 insertions, 31 deletions
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 99b3bfa717d5..9e6e9fc27d6a 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -365,15 +365,15 @@ static inline unsigned long at76_get_timeout(struct dfu_status *s) static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size, int manifest_sync_timeout) { - u8 *block; - struct dfu_status dfu_stat_buf; int ret = 0; int need_dfu_state = 1; int is_done = 0; - u8 dfu_state = 0; u32 dfu_timeout = 0; int bsize = 0; int blockno = 0; + struct dfu_status *dfu_stat_buf = NULL; + u8 *dfu_state = NULL; + u8 *block = NULL; at76_dbg(DBG_DFU, "%s( %p, %u, %d)", __func__, buf, size, manifest_sync_timeout); @@ -383,13 +383,28 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size, return -EINVAL; } + dfu_stat_buf = kmalloc(sizeof(struct dfu_status), GFP_KERNEL); + if (!dfu_stat_buf) { + ret = -ENOMEM; + goto exit; + } + block = kmalloc(FW_BLOCK_SIZE, GFP_KERNEL); - if (!block) - return -ENOMEM; + if (!block) { + ret = -ENOMEM; + goto exit; + } + + dfu_state = kmalloc(sizeof(u8), GFP_KERNEL); + if (!dfu_state) { + ret = -ENOMEM; + goto exit; + } + *dfu_state = 0; do { if (need_dfu_state) { - ret = at76_dfu_get_state(udev, &dfu_state); + ret = at76_dfu_get_state(udev, dfu_state); if (ret < 0) { dev_err(&udev->dev, "cannot get DFU state: %d\n", ret); @@ -398,13 +413,13 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size, need_dfu_state = 0; } - switch (dfu_state) { + switch (*dfu_state) { case STATE_DFU_DOWNLOAD_SYNC: at76_dbg(DBG_DFU, "STATE_DFU_DOWNLOAD_SYNC"); - ret = at76_dfu_get_status(udev, &dfu_stat_buf); + ret = at76_dfu_get_status(udev, dfu_stat_buf); if (ret >= 0) { - dfu_state = dfu_stat_buf.state; - dfu_timeout = at76_get_timeout(&dfu_stat_buf); + *dfu_state = dfu_stat_buf->state; + dfu_timeout = at76_get_timeout(dfu_stat_buf); need_dfu_state = 0; } else dev_err(&udev->dev, @@ -447,12 +462,12 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size, case STATE_DFU_MANIFEST_SYNC: at76_dbg(DBG_DFU, "STATE_DFU_MANIFEST_SYNC"); - ret = at76_dfu_get_status(udev, &dfu_stat_buf); + ret = at76_dfu_get_status(udev, dfu_stat_buf); if (ret < 0) break; - dfu_state = dfu_stat_buf.state; - dfu_timeout = at76_get_timeout(&dfu_stat_buf); + *dfu_state = dfu_stat_buf->state; + dfu_timeout = at76_get_timeout(dfu_stat_buf); need_dfu_state = 0; /* override the timeout from the status response, @@ -484,14 +499,17 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size, break; default: - at76_dbg(DBG_DFU, "DFU UNKNOWN STATE (%d)", dfu_state); + at76_dbg(DBG_DFU, "DFU UNKNOWN STATE (%d)", *dfu_state); ret = -EINVAL; break; } } while (!is_done && (ret >= 0)); exit: + kfree(dfu_state); kfree(block); + kfree(dfu_stat_buf); + if (ret >= 0) ret = 0; @@ -1277,6 +1295,7 @@ static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe) dev_err(&udev->dev, "loading %dth firmware block failed: %d\n", blockno, ret); + ret = -EIO; goto exit; } buf += bsize; @@ -2330,16 +2349,22 @@ static int at76_probe(struct usb_interface *interface, struct usb_device *udev; int op_mode; int need_ext_fw = 0; - struct mib_fw_version fwv; + struct mib_fw_version *fwv = NULL; int board_type = (int)id->driver_info; udev = usb_get_dev(interface_to_usbdev(interface)); + fwv = kmalloc(sizeof(*fwv), GFP_KERNEL); + if (!fwv) { + ret = -ENOMEM; + goto exit; + } + /* Load firmware into kernel memory */ fwe = at76_load_firmware(udev, board_type); if (!fwe) { ret = -ENOENT; - goto error; + goto exit; } op_mode = at76_get_op_mode(udev); @@ -2353,7 +2378,7 @@ static int at76_probe(struct usb_interface *interface, dev_err(&interface->dev, "cannot handle a device in HW_CONFIG_MODE\n"); ret = -EBUSY; - goto error; + goto exit; } if (op_mode != OPMODE_NORMAL_NIC_WITH_FLASH @@ -2366,10 +2391,10 @@ static int at76_probe(struct usb_interface *interface, dev_err(&interface->dev, "error %d downloading internal firmware\n", ret); - goto error; + goto exit; } usb_put_dev(udev); - return ret; + goto exit; } /* Internal firmware already inside the device. Get firmware @@ -2382,8 +2407,8 @@ static int at76_probe(struct usb_interface *interface, * query the device for the fw version */ if ((fwe->fw_version.major > 0 || fwe->fw_version.minor >= 100) || (op_mode == OPMODE_NORMAL_NIC_WITH_FLASH)) { - ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv)); - if (ret < 0 || (fwv.major | fwv.minor) == 0) + ret = at76_get_mib(udev, MIB_FW_VERSION, fwv, sizeof(*fwv)); + if (ret < 0 || (fwv->major | fwv->minor) == 0) need_ext_fw = 1; } else /* No way to check firmware version, reload to be sure */ @@ -2394,37 +2419,37 @@ static int at76_probe(struct usb_interface *interface, "downloading external firmware\n"); ret = at76_load_external_fw(udev, fwe); - if (ret) - goto error; + if (ret < 0) + goto exit; /* Re-check firmware version */ - ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv)); + ret = at76_get_mib(udev, MIB_FW_VERSION, fwv, sizeof(*fwv)); if (ret < 0) { dev_err(&interface->dev, "error %d getting firmware version\n", ret); - goto error; + goto exit; } } priv = at76_alloc_new_device(udev); if (!priv) { ret = -ENOMEM; - goto error; + goto exit; } usb_set_intfdata(interface, priv); - memcpy(&priv->fw_version, &fwv, sizeof(struct mib_fw_version)); + memcpy(&priv->fw_version, fwv, sizeof(struct mib_fw_version)); priv->board_type = board_type; ret = at76_init_new_device(priv, interface); if (ret < 0) at76_delete_device(priv); - return ret; - -error: - usb_put_dev(udev); +exit: + kfree(fwv); + if (ret < 0) + usb_put_dev(udev); return ret; } |