blob: abc7a7ab782a3895c19a34eda5c77dce7eed548d [file] [log] [blame]
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001#include "headers.h"
2
Marcos Paulo de Souza43664e12011-09-23 00:20:09 -03003int InterfaceFileDownload(PVOID arg, struct file *flp, unsigned int on_chip_loc)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07004{
Kevin McKinneya5e4b812011-10-20 08:15:22 -04005 /* unsigned int reg = 0; */
Marcos Paulo de Souza43664e12011-09-23 00:20:09 -03006 mm_segment_t oldfs = {0};
Kevin McKinneya5e4b812011-10-20 08:15:22 -04007 int errno = 0, len = 0; /* ,is_config_file = 0 */
Marcos Paulo de Souza43664e12011-09-23 00:20:09 -03008 loff_t pos = 0;
Lisa Nguyen2fef7e12013-10-29 14:19:50 -07009 struct bcm_interface_adapter *psIntfAdapter = arg;
Kevin McKinney29794602012-05-26 12:05:12 -040010 /* struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter; */
Marcos Paulo de Souza43664e12011-09-23 00:20:09 -030011 char *buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070012
Marcos Paulo de Souza43664e12011-09-23 00:20:09 -030013 if (!buff)
14 return -ENOMEM;
15
16 while (1) {
17 oldfs = get_fs();
18 set_fs(get_ds());
19 len = vfs_read(flp, (void __force __user *)buff,
Kevin McKinneya5e4b812011-10-20 08:15:22 -040020 MAX_TRANSFER_CTRL_BYTE_USB, &pos);
Marcos Paulo de Souza43664e12011-09-23 00:20:09 -030021 set_fs(oldfs);
22 if (len <= 0) {
Gokulnath A8f5157b2013-12-18 23:12:37 +053023 if (len < 0)
Marcos Paulo de Souza43664e12011-09-23 00:20:09 -030024 errno = len;
Gokulnath A8f5157b2013-12-18 23:12:37 +053025 else
Marcos Paulo de Souza43664e12011-09-23 00:20:09 -030026 errno = 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070027 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070028 }
Marcos Paulo de Souza43664e12011-09-23 00:20:09 -030029 /* BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT,
Kevin McKinneya5e4b812011-10-20 08:15:22 -040030 * DBG_LVL_ALL, buff,
31 * MAX_TRANSFER_CTRL_BYTE_USB);
32 */
Marcos Paulo de Souza43664e12011-09-23 00:20:09 -030033 errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len);
Gokulnath A8f5157b2013-12-18 23:12:37 +053034 if (errno)
Marcos Paulo de Souza43664e12011-09-23 00:20:09 -030035 break;
Marcos Paulo de Souza43664e12011-09-23 00:20:09 -030036 on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
37 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070038
Stephen Hemminger082e8892010-11-01 09:35:21 -040039 kfree(buff);
Marcos Paulo de Souza43664e12011-09-23 00:20:09 -030040 return errno;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070041}
42
Gokulnath Ab3a53882013-12-18 23:12:38 +053043int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp,
44 unsigned int on_chip_loc)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070045{
Marcos Paulo de Souza43664e12011-09-23 00:20:09 -030046 char *buff, *buff_readback;
47 unsigned int reg = 0;
Kevin McKinneya5e4b812011-10-20 08:15:22 -040048 mm_segment_t oldfs = {0};
49 int errno = 0, len = 0, is_config_file = 0;
50 loff_t pos = 0;
Kevin McKinneya8658182011-10-20 08:15:23 -040051 static int fw_down;
Kevin McKinneya5e4b812011-10-20 08:15:22 -040052 INT Status = STATUS_SUCCESS;
Lisa Nguyen2fef7e12013-10-29 14:19:50 -070053 struct bcm_interface_adapter *psIntfAdapter = arg;
Kevin McKinney41c7b7c2011-11-06 09:40:11 -050054 int bytes;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070055
Daeseok Youn87755c02014-05-07 15:01:04 +090056 buff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA);
57 buff_readback = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA);
Kevin McKinneya5e4b812011-10-20 08:15:22 -040058 if (!buff || !buff_readback) {
59 kfree(buff);
60 kfree(buff_readback);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070061
Kevin McKinneya5e4b812011-10-20 08:15:22 -040062 return -ENOMEM;
63 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070064
Kevin McKinneya5e4b812011-10-20 08:15:22 -040065 is_config_file = (on_chip_loc == CONFIG_BEGIN_ADDR) ? 1 : 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070066
Kevin McKinneya5e4b812011-10-20 08:15:22 -040067 while (1) {
68 oldfs = get_fs();
69 set_fs(get_ds());
Gokulnath Ab3a53882013-12-18 23:12:38 +053070 len = vfs_read(flp, (void __force __user *)buff,
71 MAX_TRANSFER_CTRL_BYTE_USB, &pos);
Kevin McKinneya5e4b812011-10-20 08:15:22 -040072 set_fs(oldfs);
73 fw_down++;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070074
Kevin McKinneya5e4b812011-10-20 08:15:22 -040075 if (len <= 0) {
Gokulnath A8f5157b2013-12-18 23:12:37 +053076 if (len < 0)
Kevin McKinneya5e4b812011-10-20 08:15:22 -040077 errno = len;
Gokulnath A8f5157b2013-12-18 23:12:37 +053078 else
Kevin McKinneya5e4b812011-10-20 08:15:22 -040079 errno = 0;
Kevin McKinneya5e4b812011-10-20 08:15:22 -040080 break;
81 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070082
Gokulnath Ab3a53882013-12-18 23:12:38 +053083 bytes = InterfaceRDM(psIntfAdapter, on_chip_loc,
84 buff_readback, len);
Kevin McKinney41c7b7c2011-11-06 09:40:11 -050085 if (bytes < 0) {
86 Status = bytes;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070087 goto exit;
88 }
89 reg++;
Kevin McKinneya5e4b812011-10-20 08:15:22 -040090 if ((len-sizeof(unsigned int)) < 4) {
91 if (memcmp(buff_readback, buff, len)) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070092 Status = -EIO;
93 goto exit;
Kevin McKinneya5e4b812011-10-20 08:15:22 -040094 }
95 } else {
96 len -= 4;
97
98 while (len) {
Gokulnath Ab3a53882013-12-18 23:12:38 +053099 if (*(unsigned int *)&buff_readback[len] !=
100 *(unsigned int *)&buff[len]) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700101 Status = -EIO;
102 goto exit;
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400103 }
104 len -= 4;
105 }
106 }
107 on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
108 } /* End of while(1) */
109
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700110exit:
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400111 kfree(buff);
112 kfree(buff_readback);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700113 return Status;
114}
115
Gokulnath Ab3a53882013-12-18 23:12:38 +0530116static int bcm_download_config_file(struct bcm_mini_adapter *Adapter,
117 struct bcm_firmware_info *psFwInfo)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700118{
119 int retval = STATUS_SUCCESS;
120 B_UINT32 value = 0;
121
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400122 if (Adapter->pstargetparams == NULL) {
Gokulnath Ab3a53882013-12-18 23:12:38 +0530123 Adapter->pstargetparams =
124 kmalloc(sizeof(struct bcm_target_params), GFP_KERNEL);
Kevin McKinneya8658182011-10-20 08:15:23 -0400125 if (Adapter->pstargetparams == NULL)
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400126 return -ENOMEM;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700127 }
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400128
Kevin McKinneyc8182332012-12-17 17:35:20 -0500129 if (psFwInfo->u32FirmwareLength != sizeof(struct bcm_target_params))
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400130 return -EIO;
131
Gokulnath Ab3a53882013-12-18 23:12:38 +0530132 retval = copy_from_user(Adapter->pstargetparams,
133 psFwInfo->pvMappedFirmwareAddress,
134 psFwInfo->u32FirmwareLength);
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400135 if (retval) {
Stephen Hemminger082e8892010-11-01 09:35:21 -0400136 kfree(Adapter->pstargetparams);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700137 Adapter->pstargetparams = NULL;
Dan Carpenteref5d2052010-10-08 14:56:58 +0200138 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700139 }
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400140
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700141 /* Parse the structure and then Download the Firmware */
142 beceem_parse_target_struct(Adapter);
143
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400144 /* Initializing the NVM. */
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700145 BcmInitNVM(Adapter);
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400146 retval = InitLedSettings(Adapter);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700147
Gokulnath A8f5157b2013-12-18 23:12:37 +0530148 if (retval)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700149 return retval;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700150
Gokulnath Ab3a53882013-12-18 23:12:38 +0530151 if (Adapter->LEDInfo.led_thread_running &
152 BCM_LED_THREAD_RUNNING_ACTIVELY) {
Lisa Nguyenf70c8a92013-10-28 01:36:19 -0700153 Adapter->LEDInfo.bLedInitDone = false;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700154 Adapter->DriverState = DRIVER_INIT;
155 wake_up(&Adapter->LEDInfo.notify_led_event);
156 }
157
Gokulnath Ab3a53882013-12-18 23:12:38 +0530158 if (Adapter->LEDInfo.led_thread_running &
159 BCM_LED_THREAD_RUNNING_ACTIVELY) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700160 Adapter->DriverState = FW_DOWNLOAD;
161 wake_up(&Adapter->LEDInfo.notify_led_event);
162 }
163
164 /* Initialize the DDR Controller */
165 retval = ddr_init(Adapter);
Gokulnath A8f5157b2013-12-18 23:12:37 +0530166 if (retval)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700167 return retval;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700168
169 value = 0;
Gokulnath Ab3a53882013-12-18 23:12:38 +0530170 wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4,
171 &value, sizeof(value));
172 wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8,
173 &value, sizeof(value));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700174
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400175 if (Adapter->eNVMType == NVM_FLASH) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700176 retval = PropagateCalParamsFromFlashToMemory(Adapter);
Gokulnath A8f5157b2013-12-18 23:12:37 +0530177 if (retval)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700178 return retval;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700179 }
180
Gokulnath Ab3a53882013-12-18 23:12:38 +0530181 retval = buffDnldVerify(Adapter, (PUCHAR)Adapter->pstargetparams,
182 sizeof(struct bcm_target_params), CONFIG_BEGIN_ADDR);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700183
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400184 if (retval)
Gokulnath Ab3a53882013-12-18 23:12:38 +0530185 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT,
186 MP_INIT, DBG_LVL_ALL,
187 "configuration file not downloaded properly");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700188 else
189 Adapter->bCfgDownloaded = TRUE;
190
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700191 return retval;
192}
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400193
Gokulnath Ab3a53882013-12-18 23:12:38 +0530194int bcm_ioctl_fw_download(struct bcm_mini_adapter *Adapter,
195 struct bcm_firmware_info *psFwInfo)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700196{
197 int retval = STATUS_SUCCESS;
198 PUCHAR buff = NULL;
199
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400200 /* Config File is needed for the Driver to download the Config file and
201 * Firmware. Check for the Config file to be first to be sent from the
202 * Application
203 */
Lisa Nguyenf70c8a92013-10-28 01:36:19 -0700204 atomic_set(&Adapter->uiMBupdate, false);
Gokulnath Ab3a53882013-12-18 23:12:38 +0530205 if (!Adapter->bCfgDownloaded &&
206 psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR) {
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400207 /* Can't Download Firmware. */
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700208 return -EINVAL;
209 }
210
211 /* If Config File, Finish the DDR Settings and then Download CFG File */
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400212 if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) {
213 retval = bcm_download_config_file(Adapter, psFwInfo);
214 } else {
215 buff = kzalloc(psFwInfo->u32FirmwareLength, GFP_KERNEL);
Gokulnath A8f5157b2013-12-18 23:12:37 +0530216 if (buff == NULL)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700217 return -ENOMEM;
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400218
Gokulnath Ab3a53882013-12-18 23:12:38 +0530219 retval = copy_from_user(buff,
220 psFwInfo->pvMappedFirmwareAddress,
221 psFwInfo->u32FirmwareLength);
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400222 if (retval != STATUS_SUCCESS) {
Dan Carpenteref5d2052010-10-08 14:56:58 +0200223 retval = -EFAULT;
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400224 goto error;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700225 }
226
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700227 retval = buffDnldVerify(Adapter,
228 buff,
229 psFwInfo->u32FirmwareLength,
230 psFwInfo->u32StartingAddress);
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400231
Gokulnath A8f5157b2013-12-18 23:12:37 +0530232 if (retval != STATUS_SUCCESS)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700233 goto error;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700234 }
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400235
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700236error:
Stephen Hemminger082e8892010-11-01 09:35:21 -0400237 kfree(buff);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700238 return retval;
239}
240
Gokulnath Ab3a53882013-12-18 23:12:38 +0530241static INT buffDnld(struct bcm_mini_adapter *Adapter,
242 PUCHAR mappedbuffer, UINT u32FirmwareLength,
243 ULONG u32StartingAddress)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700244{
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400245 unsigned int len = 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700246 int retval = STATUS_SUCCESS;
Pawel Lebioda89fa0372014-07-09 17:59:29 +0200247
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700248 len = u32FirmwareLength;
249
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400250 while (u32FirmwareLength) {
251 len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
252 retval = wrm(Adapter, u32StartingAddress, mappedbuffer, len);
253
Gokulnath A8f5157b2013-12-18 23:12:37 +0530254 if (retval)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700255 break;
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400256 u32StartingAddress += len;
257 u32FirmwareLength -= len;
258 mappedbuffer += len;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700259 }
260 return retval;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700261}
262
Gokulnath Ab3a53882013-12-18 23:12:38 +0530263static INT buffRdbkVerify(struct bcm_mini_adapter *Adapter,
264 PUCHAR mappedbuffer, UINT u32FirmwareLength,
265 ULONG u32StartingAddress)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700266{
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700267 UINT len = u32FirmwareLength;
268 INT retval = STATUS_SUCCESS;
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400269 PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500270 int bytes;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700271
Gokulnath A8f5157b2013-12-18 23:12:37 +0530272 if (NULL == readbackbuff)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700273 return -ENOMEM;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700274
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400275 while (u32FirmwareLength && !retval) {
276 len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500277 bytes = rdm(Adapter, u32StartingAddress, readbackbuff, len);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700278
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500279 if (bytes < 0) {
280 retval = bytes;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700281 break;
282 }
283
Dan Carpenter2c5270a2013-03-01 23:28:06 +0300284 if (memcmp(readbackbuff, mappedbuffer, len) != 0) {
285 pr_err("%s() failed. The firmware doesn't match what was written",
286 __func__);
287 retval = -EIO;
288 }
Kevin McKinneya5e4b812011-10-20 08:15:22 -0400289
290 u32StartingAddress += len;
291 u32FirmwareLength -= len;
292 mappedbuffer += len;
293
294 } /* end of while (u32FirmwareLength && !retval) */
Stephen Hemminger082e8892010-11-01 09:35:21 -0400295 kfree(readbackbuff);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700296 return retval;
297}
298
Gokulnath Ab3a53882013-12-18 23:12:38 +0530299INT buffDnldVerify(struct bcm_mini_adapter *Adapter,
300 unsigned char *mappedbuffer,
301 unsigned int u32FirmwareLength,
302 unsigned long u32StartingAddress)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700303{
304 INT status = STATUS_SUCCESS;
305
Gokulnath Ab3a53882013-12-18 23:12:38 +0530306 status = buffDnld(Adapter, mappedbuffer,
307 u32FirmwareLength, u32StartingAddress);
Gokulnath A8f5157b2013-12-18 23:12:37 +0530308 if (status != STATUS_SUCCESS)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700309 goto error;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700310
Gokulnath Ab3a53882013-12-18 23:12:38 +0530311 status = buffRdbkVerify(Adapter, mappedbuffer,
312 u32FirmwareLength, u32StartingAddress);
Gokulnath A8f5157b2013-12-18 23:12:37 +0530313 if (status != STATUS_SUCCESS)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700314 goto error;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700315error:
316 return status;
317}