]> Pileus Git - ~andy/linux/blob - drivers/staging/bcm/InterfaceDld.c
Merge tag 'stable/for-linus-3.14-rc5-tag' of git://git.kernel.org/pub/scm/linux/kerne...
[~andy/linux] / drivers / staging / bcm / InterfaceDld.c
1 #include "headers.h"
2
3 int InterfaceFileDownload(PVOID arg, struct file *flp, unsigned int on_chip_loc)
4 {
5         /* unsigned int reg = 0; */
6         mm_segment_t oldfs = {0};
7         int errno = 0, len = 0; /* ,is_config_file = 0 */
8         loff_t pos = 0;
9         struct bcm_interface_adapter *psIntfAdapter = arg;
10         /* struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter; */
11         char *buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
12
13         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,
20                         MAX_TRANSFER_CTRL_BYTE_USB, &pos);
21                 set_fs(oldfs);
22                 if (len <= 0) {
23                         if (len < 0)
24                                 errno = len;
25                         else
26                                 errno = 0;
27                         break;
28                 }
29                 /* BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT,
30                  *                        DBG_LVL_ALL, buff,
31                  *                        MAX_TRANSFER_CTRL_BYTE_USB);
32                  */
33                 errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len);
34                 if (errno)
35                         break;
36                 on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
37         }
38
39         kfree(buff);
40         return errno;
41 }
42
43 int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp,
44                                 unsigned int on_chip_loc)
45 {
46         char *buff, *buff_readback;
47         unsigned int reg = 0;
48         mm_segment_t oldfs = {0};
49         int errno = 0, len = 0, is_config_file = 0;
50         loff_t pos = 0;
51         static int fw_down;
52         INT Status = STATUS_SUCCESS;
53         struct bcm_interface_adapter *psIntfAdapter = arg;
54         int bytes;
55
56         buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA);
57         buff_readback = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA);
58         if (!buff || !buff_readback) {
59                 kfree(buff);
60                 kfree(buff_readback);
61
62                 return -ENOMEM;
63         }
64
65         is_config_file = (on_chip_loc == CONFIG_BEGIN_ADDR) ? 1 : 0;
66
67         memset(buff_readback, 0, MAX_TRANSFER_CTRL_BYTE_USB);
68         memset(buff, 0, MAX_TRANSFER_CTRL_BYTE_USB);
69         while (1) {
70                 oldfs = get_fs();
71                 set_fs(get_ds());
72                 len = vfs_read(flp, (void __force __user *)buff,
73                                 MAX_TRANSFER_CTRL_BYTE_USB, &pos);
74                 set_fs(oldfs);
75                 fw_down++;
76
77                 if (len <= 0) {
78                         if (len < 0)
79                                 errno = len;
80                         else
81                                 errno = 0;
82                         break;
83                 }
84
85                 bytes = InterfaceRDM(psIntfAdapter, on_chip_loc,
86                                         buff_readback, len);
87                 if (bytes < 0) {
88                         Status = bytes;
89                         goto exit;
90                 }
91                 reg++;
92                 if ((len-sizeof(unsigned int)) < 4) {
93                         if (memcmp(buff_readback, buff, len)) {
94                                 Status = -EIO;
95                                 goto exit;
96                         }
97                 } else {
98                         len -= 4;
99
100                         while (len) {
101                                 if (*(unsigned int *)&buff_readback[len] !=
102                                                  *(unsigned int *)&buff[len]) {
103                                         Status = -EIO;
104                                         goto exit;
105                                 }
106                                 len -= 4;
107                         }
108                 }
109                 on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
110         } /* End of while(1) */
111
112 exit:
113         kfree(buff);
114         kfree(buff_readback);
115         return Status;
116 }
117
118 static int bcm_download_config_file(struct bcm_mini_adapter *Adapter,
119                                 struct bcm_firmware_info *psFwInfo)
120 {
121         int retval = STATUS_SUCCESS;
122         B_UINT32 value = 0;
123
124         if (Adapter->pstargetparams == NULL) {
125                 Adapter->pstargetparams =
126                         kmalloc(sizeof(struct bcm_target_params), GFP_KERNEL);
127                 if (Adapter->pstargetparams == NULL)
128                         return -ENOMEM;
129         }
130
131         if (psFwInfo->u32FirmwareLength != sizeof(struct bcm_target_params))
132                 return -EIO;
133
134         retval = copy_from_user(Adapter->pstargetparams,
135                         psFwInfo->pvMappedFirmwareAddress,
136                         psFwInfo->u32FirmwareLength);
137         if (retval) {
138                 kfree(Adapter->pstargetparams);
139                 Adapter->pstargetparams = NULL;
140                 return -EFAULT;
141         }
142
143         /* Parse the structure and then Download the Firmware */
144         beceem_parse_target_struct(Adapter);
145
146         /* Initializing the NVM. */
147         BcmInitNVM(Adapter);
148         retval = InitLedSettings(Adapter);
149
150         if (retval)
151                 return retval;
152
153         if (Adapter->LEDInfo.led_thread_running &
154                         BCM_LED_THREAD_RUNNING_ACTIVELY) {
155                 Adapter->LEDInfo.bLedInitDone = false;
156                 Adapter->DriverState = DRIVER_INIT;
157                 wake_up(&Adapter->LEDInfo.notify_led_event);
158         }
159
160         if (Adapter->LEDInfo.led_thread_running &
161                         BCM_LED_THREAD_RUNNING_ACTIVELY) {
162                 Adapter->DriverState = FW_DOWNLOAD;
163                 wake_up(&Adapter->LEDInfo.notify_led_event);
164         }
165
166         /* Initialize the DDR Controller */
167         retval = ddr_init(Adapter);
168         if (retval)
169                 return retval;
170
171         value = 0;
172         wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4,
173                                 &value, sizeof(value));
174         wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8,
175                                 &value, sizeof(value));
176
177         if (Adapter->eNVMType == NVM_FLASH) {
178                 retval = PropagateCalParamsFromFlashToMemory(Adapter);
179                 if (retval)
180                         return retval;
181         }
182
183         retval = buffDnldVerify(Adapter, (PUCHAR)Adapter->pstargetparams,
184                         sizeof(struct bcm_target_params), CONFIG_BEGIN_ADDR);
185
186         if (retval)
187                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT,
188                                 MP_INIT, DBG_LVL_ALL,
189                                 "configuration file not downloaded properly");
190         else
191                 Adapter->bCfgDownloaded = TRUE;
192
193         return retval;
194 }
195
196 int bcm_ioctl_fw_download(struct bcm_mini_adapter *Adapter,
197                         struct bcm_firmware_info *psFwInfo)
198 {
199         int retval = STATUS_SUCCESS;
200         PUCHAR buff = NULL;
201
202         /* Config File is needed for the Driver to download the Config file and
203          * Firmware. Check for the Config file to be first to be sent from the
204          * Application
205          */
206         atomic_set(&Adapter->uiMBupdate, false);
207         if (!Adapter->bCfgDownloaded &&
208                 psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR) {
209                 /* Can't Download Firmware. */
210                 return -EINVAL;
211         }
212
213         /* If Config File, Finish the DDR Settings and then Download CFG File */
214         if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) {
215                 retval = bcm_download_config_file(Adapter, psFwInfo);
216         } else {
217                 buff = kzalloc(psFwInfo->u32FirmwareLength, GFP_KERNEL);
218                 if (buff == NULL)
219                         return -ENOMEM;
220
221                 retval = copy_from_user(buff,
222                         psFwInfo->pvMappedFirmwareAddress,
223                         psFwInfo->u32FirmwareLength);
224                 if (retval != STATUS_SUCCESS) {
225                         retval = -EFAULT;
226                         goto error;
227                 }
228
229                 retval = buffDnldVerify(Adapter,
230                                         buff,
231                                         psFwInfo->u32FirmwareLength,
232                                         psFwInfo->u32StartingAddress);
233
234                 if (retval != STATUS_SUCCESS)
235                         goto error;
236         }
237
238 error:
239         kfree(buff);
240         return retval;
241 }
242
243 static INT buffDnld(struct bcm_mini_adapter *Adapter,
244                         PUCHAR mappedbuffer, UINT u32FirmwareLength,
245                         ULONG u32StartingAddress)
246 {
247         unsigned int len = 0;
248         int retval = STATUS_SUCCESS;
249         len = u32FirmwareLength;
250
251         while (u32FirmwareLength) {
252                 len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
253                 retval = wrm(Adapter, u32StartingAddress, mappedbuffer, len);
254
255                 if (retval)
256                         break;
257                 u32StartingAddress += len;
258                 u32FirmwareLength -= len;
259                 mappedbuffer += len;
260         }
261         return retval;
262 }
263
264 static INT buffRdbkVerify(struct bcm_mini_adapter *Adapter,
265                         PUCHAR mappedbuffer, UINT u32FirmwareLength,
266                         ULONG u32StartingAddress)
267 {
268         UINT len = u32FirmwareLength;
269         INT retval = STATUS_SUCCESS;
270         PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
271         int bytes;
272
273         if (NULL == readbackbuff)
274                 return -ENOMEM;
275
276         while (u32FirmwareLength && !retval) {
277                 len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
278                 bytes = rdm(Adapter, u32StartingAddress, readbackbuff, len);
279
280                 if (bytes < 0) {
281                         retval = bytes;
282                         break;
283                 }
284
285                 if (memcmp(readbackbuff, mappedbuffer, len) != 0) {
286                         pr_err("%s() failed.  The firmware doesn't match what was written",
287                                __func__);
288                         retval = -EIO;
289                 }
290
291                 u32StartingAddress += len;
292                 u32FirmwareLength -= len;
293                 mappedbuffer += len;
294
295         } /* end of while (u32FirmwareLength && !retval) */
296         kfree(readbackbuff);
297         return retval;
298 }
299
300 INT buffDnldVerify(struct bcm_mini_adapter *Adapter,
301                         unsigned char *mappedbuffer,
302                         unsigned int u32FirmwareLength,
303                         unsigned long u32StartingAddress)
304 {
305         INT status = STATUS_SUCCESS;
306
307         status = buffDnld(Adapter, mappedbuffer,
308                         u32FirmwareLength, u32StartingAddress);
309         if (status != STATUS_SUCCESS)
310                 goto error;
311
312         status = buffRdbkVerify(Adapter, mappedbuffer,
313                         u32FirmwareLength, u32StartingAddress);
314         if (status != STATUS_SUCCESS)
315                 goto error;
316 error:
317         return status;
318 }