From: Ben Hutchings Date: Sun, 9 Jan 2011 04:16:48 +0000 Subject: [PATCH] vt6656: Use request_firmware() to load firmware commit 31d5bbf3da8c3c9de5944f2c09cbc7ea5a72bdb4 upstream. The file added to linux-firmware is a copy of the current array which does not have a recognisable header, so no validation is done. Change the firmware version check to accept newer versions. Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman [bwh: Restore firmware.c without the firmware blob] --- --- a/drivers/staging/vt6656/firmware.c +++ b/drivers/staging/vt6656/firmware.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * + * File: baseband.c + * + * Purpose: Implement functions to access baseband + * + * Author: Yiching Chen + * + * Date: May 20, 2004 + * + * Functions: + * + * Revision History: + * + */ + +#include "firmware.h" +#include "control.h" +#include "rndis.h" + +/*--------------------- Static Definitions -------------------------*/ + +static int msglevel =MSG_LEVEL_INFO; +//static int msglevel =MSG_LEVEL_DEBUG; + +#define FIRMWARE_VERSION 0x133 /* version 1.51 */ +#define FIRMWARE_NAME "vntwusb.fw" + +#define FIRMWARE_CHUNK_SIZE 0x400 + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ + +/*--------------------- Static Functions --------------------------*/ + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + + +BOOL +FIRMWAREbDownload( + PSDevice pDevice + ) +{ + const struct firmware *fw; + int NdisStatus; + void *pBuffer = NULL; + BOOL result = FALSE; + u16 wLength; + int ii; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Download firmware\n"); + spin_unlock_irq(&pDevice->lock); + + if (!pDevice->firmware) { + struct device *dev = &pDevice->usb->dev; + int rc; + + rc = request_firmware(&pDevice->firmware, FIRMWARE_NAME, dev); + if (rc) { + dev_err(dev, "firmware file %s request failed (%d)\n", + FIRMWARE_NAME, rc); + goto out; + } + } + fw = pDevice->firmware; + + pBuffer = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL); + if (!pBuffer) + goto out; + + for (ii = 0; ii < fw->size; ii += FIRMWARE_CHUNK_SIZE) { + wLength = min_t(int, fw->size - ii, FIRMWARE_CHUNK_SIZE); + memcpy(pBuffer, fw->data + ii, wLength); + + NdisStatus = CONTROLnsRequestOutAsyn(pDevice, + 0, + 0x1200+ii, + 0x0000, + wLength, + pBuffer + ); + + DBG_PRT(MSG_LEVEL_DEBUG, + KERN_INFO"Download firmware...%d %zu\n", ii, fw->size); + if (NdisStatus != STATUS_SUCCESS) + goto out; + } + + result = TRUE; + +out: + if (pBuffer) + kfree(pBuffer); + + spin_lock_irq(&pDevice->lock); + return result; +} +MODULE_FIRMWARE(FIRMWARE_NAME); + +BOOL +FIRMWAREbBrach2Sram( + PSDevice pDevice + ) +{ + int NdisStatus; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Branch to Sram\n"); + + NdisStatus = CONTROLnsRequestOut(pDevice, + 1, + 0x1200, + 0x0000, + 0, + NULL + ); + + if (NdisStatus != STATUS_SUCCESS) { + return (FALSE); + } else { + return (TRUE); + } +} + + +BOOL +FIRMWAREbCheckVersion( + PSDevice pDevice + ) +{ + int ntStatus; + + ntStatus = CONTROLnsRequestIn(pDevice, + MESSAGE_TYPE_READ, + 0, + MESSAGE_REQUEST_VERSION, + 2, + (PBYTE) &(pDevice->wFirmwareVersion)); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Version [%04x]\n", pDevice->wFirmwareVersion); + if (ntStatus != STATUS_SUCCESS) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Invalid.\n"); + return FALSE; + } + if (pDevice->wFirmwareVersion == 0xFFFF) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"In Loader.\n"); + return FALSE; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Version [%04x]\n", pDevice->wFirmwareVersion); + if (pDevice->wFirmwareVersion < FIRMWARE_VERSION) { + // branch to loader for download new firmware + FIRMWAREbBrach2Sram(pDevice); + return FALSE; + } + return TRUE; +} --- a/drivers/staging/vt6656/Kconfig +++ b/drivers/staging/vt6656/Kconfig @@ -3,6 +3,7 @@ config VT6656 depends on USB && WLAN select WIRELESS_EXT select WEXT_PRIV + select FW_LOADER ---help--- This is a vendor-written driver for VIA VT6656. --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #ifdef SIOCETHTOOL @@ -421,6 +422,8 @@ typedef struct __device_info { struct net_device* dev; struct net_device_stats stats; + const struct firmware *firmware; + OPTIONS sOpts; struct tasklet_struct CmdWorkItem; --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1272,6 +1272,9 @@ static void __devexit vt6656_disconnect(struct usb_interface *intf) device_release_WPADEV(device); + if (device->firmware) + release_firmware(device->firmware); + usb_set_intfdata(intf, NULL); usb_put_dev(interface_to_usbdev(intf));