PM / sleep: Asynchronous threads for suspend_noirq
[linux/fpc-iii.git] / drivers / staging / bcm / InterfaceDld.c
blob005e4607b2600770f35e7647cf841899c6d46440
1 #include "headers.h"
3 int InterfaceFileDownload(PVOID arg, struct file *flp, unsigned int on_chip_loc)
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);
13 if (!buff)
14 return -ENOMEM;
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;
29 /* BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT,
30 * DBG_LVL_ALL, buff,
31 * MAX_TRANSFER_CTRL_BYTE_USB);
33 errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len);
34 if (errno)
35 break;
36 on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
39 kfree(buff);
40 return errno;
43 int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp,
44 unsigned int on_chip_loc)
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;
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);
62 return -ENOMEM;
65 is_config_file = (on_chip_loc == CONFIG_BEGIN_ADDR) ? 1 : 0;
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++;
77 if (len <= 0) {
78 if (len < 0)
79 errno = len;
80 else
81 errno = 0;
82 break;
85 bytes = InterfaceRDM(psIntfAdapter, on_chip_loc,
86 buff_readback, len);
87 if (bytes < 0) {
88 Status = bytes;
89 goto exit;
91 reg++;
92 if ((len-sizeof(unsigned int)) < 4) {
93 if (memcmp(buff_readback, buff, len)) {
94 Status = -EIO;
95 goto exit;
97 } else {
98 len -= 4;
100 while (len) {
101 if (*(unsigned int *)&buff_readback[len] !=
102 *(unsigned int *)&buff[len]) {
103 Status = -EIO;
104 goto exit;
106 len -= 4;
109 on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
110 } /* End of while(1) */
112 exit:
113 kfree(buff);
114 kfree(buff_readback);
115 return Status;
118 static int bcm_download_config_file(struct bcm_mini_adapter *Adapter,
119 struct bcm_firmware_info *psFwInfo)
121 int retval = STATUS_SUCCESS;
122 B_UINT32 value = 0;
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;
131 if (psFwInfo->u32FirmwareLength != sizeof(struct bcm_target_params))
132 return -EIO;
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;
143 /* Parse the structure and then Download the Firmware */
144 beceem_parse_target_struct(Adapter);
146 /* Initializing the NVM. */
147 BcmInitNVM(Adapter);
148 retval = InitLedSettings(Adapter);
150 if (retval)
151 return retval;
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);
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);
166 /* Initialize the DDR Controller */
167 retval = ddr_init(Adapter);
168 if (retval)
169 return retval;
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));
177 if (Adapter->eNVMType == NVM_FLASH) {
178 retval = PropagateCalParamsFromFlashToMemory(Adapter);
179 if (retval)
180 return retval;
183 retval = buffDnldVerify(Adapter, (PUCHAR)Adapter->pstargetparams,
184 sizeof(struct bcm_target_params), CONFIG_BEGIN_ADDR);
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;
193 return retval;
196 int bcm_ioctl_fw_download(struct bcm_mini_adapter *Adapter,
197 struct bcm_firmware_info *psFwInfo)
199 int retval = STATUS_SUCCESS;
200 PUCHAR buff = NULL;
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
206 atomic_set(&Adapter->uiMBupdate, false);
207 if (!Adapter->bCfgDownloaded &&
208 psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR) {
209 /* Can't Download Firmware. */
210 return -EINVAL;
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;
221 retval = copy_from_user(buff,
222 psFwInfo->pvMappedFirmwareAddress,
223 psFwInfo->u32FirmwareLength);
224 if (retval != STATUS_SUCCESS) {
225 retval = -EFAULT;
226 goto error;
229 retval = buffDnldVerify(Adapter,
230 buff,
231 psFwInfo->u32FirmwareLength,
232 psFwInfo->u32StartingAddress);
234 if (retval != STATUS_SUCCESS)
235 goto error;
238 error:
239 kfree(buff);
240 return retval;
243 static INT buffDnld(struct bcm_mini_adapter *Adapter,
244 PUCHAR mappedbuffer, UINT u32FirmwareLength,
245 ULONG u32StartingAddress)
247 unsigned int len = 0;
248 int retval = STATUS_SUCCESS;
249 len = u32FirmwareLength;
251 while (u32FirmwareLength) {
252 len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
253 retval = wrm(Adapter, u32StartingAddress, mappedbuffer, len);
255 if (retval)
256 break;
257 u32StartingAddress += len;
258 u32FirmwareLength -= len;
259 mappedbuffer += len;
261 return retval;
264 static INT buffRdbkVerify(struct bcm_mini_adapter *Adapter,
265 PUCHAR mappedbuffer, UINT u32FirmwareLength,
266 ULONG u32StartingAddress)
268 UINT len = u32FirmwareLength;
269 INT retval = STATUS_SUCCESS;
270 PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
271 int bytes;
273 if (NULL == readbackbuff)
274 return -ENOMEM;
276 while (u32FirmwareLength && !retval) {
277 len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
278 bytes = rdm(Adapter, u32StartingAddress, readbackbuff, len);
280 if (bytes < 0) {
281 retval = bytes;
282 break;
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;
291 u32StartingAddress += len;
292 u32FirmwareLength -= len;
293 mappedbuffer += len;
295 } /* end of while (u32FirmwareLength && !retval) */
296 kfree(readbackbuff);
297 return retval;
300 INT buffDnldVerify(struct bcm_mini_adapter *Adapter,
301 unsigned char *mappedbuffer,
302 unsigned int u32FirmwareLength,
303 unsigned long u32StartingAddress)
305 INT status = STATUS_SUCCESS;
307 status = buffDnld(Adapter, mappedbuffer,
308 u32FirmwareLength, u32StartingAddress);
309 if (status != STATUS_SUCCESS)
310 goto error;
312 status = buffRdbkVerify(Adapter, mappedbuffer,
313 u32FirmwareLength, u32StartingAddress);
314 if (status != STATUS_SUCCESS)
315 goto error;
316 error:
317 return status;