]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/bcm/Bcmchar.c
Merge tag 'clk-for-linus-3.18' of git://git.linaro.org/people/mike.turquette/linux
[karo-tx-linux.git] / drivers / staging / bcm / Bcmchar.c
1 #include <linux/fs.h>
2
3 #include "headers.h"
4
5 static int bcm_handle_nvm_read_cmd(struct bcm_mini_adapter *ad,
6                                    PUCHAR read_data,
7                                    struct bcm_nvm_readwrite *nvm_rw)
8 {
9         INT status = STATUS_FAILURE;
10
11         down(&ad->NVMRdmWrmLock);
12
13         if ((ad->IdleMode == TRUE) || (ad->bShutStatus == TRUE) ||
14                         (ad->bPreparingForLowPowerMode == TRUE)) {
15
16                 BCM_DEBUG_PRINT(ad,
17                         DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
18                         "Device is in Idle/Shutdown Mode\n");
19                 up(&ad->NVMRdmWrmLock);
20                 kfree(read_data);
21                 return -EACCES;
22         }
23
24         status = BeceemNVMRead(ad, (PUINT)read_data,
25                                nvm_rw->uiOffset,
26                                nvm_rw->uiNumBytes);
27         up(&ad->NVMRdmWrmLock);
28
29         if (status != STATUS_SUCCESS) {
30                 kfree(read_data);
31                 return status;
32         }
33
34         if (copy_to_user(nvm_rw->pBuffer, read_data, nvm_rw->uiNumBytes)) {
35                 kfree(read_data);
36                 return -EFAULT;
37         }
38
39         return STATUS_SUCCESS;
40 }
41
42 static int handle_flash2x_adapter(struct bcm_mini_adapter *ad,
43                                   PUCHAR read_data,
44                                   struct bcm_nvm_readwrite *nvm_rw)
45 {
46         /*
47          * New Requirement:-
48          * DSD section updation will be allowed in two case:-
49          * 1.  if DSD sig is present in DSD header means dongle
50          * is ok and updation is fruitfull
51          * 2.  if point 1 failes then user buff should have
52          * DSD sig. this point ensures that if dongle is
53          * corrupted then user space program first modify
54          * the DSD header with valid DSD sig so that this
55          * as well as further write may be worthwhile.
56          *
57          * This restriction has been put assuming that
58          * if DSD sig is corrupted, DSD data won't be
59          * considered valid.
60          */
61         INT status;
62         ULONG dsd_magic_num_in_usr_buff = 0;
63
64         status = BcmFlash2xCorruptSig(ad, ad->eActiveDSD);
65         if (status == STATUS_SUCCESS)
66                 return STATUS_SUCCESS;
67
68         if (((nvm_rw->uiOffset + nvm_rw->uiNumBytes) !=
69                         ad->uiNVMDSDSize) ||
70                         (nvm_rw->uiNumBytes < SIGNATURE_SIZE)) {
71
72                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
73                                 "DSD Sig is present neither in Flash nor User provided Input..");
74                 up(&ad->NVMRdmWrmLock);
75                 kfree(read_data);
76                 return status;
77         }
78
79         dsd_magic_num_in_usr_buff =
80                 ntohl(*(PUINT)(read_data + nvm_rw->uiNumBytes -
81                       SIGNATURE_SIZE));
82         if (dsd_magic_num_in_usr_buff != DSD_IMAGE_MAGIC_NUMBER) {
83                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
84                                 "DSD Sig is present neither in Flash nor User provided Input..");
85                 up(&ad->NVMRdmWrmLock);
86                 kfree(read_data);
87                 return status;
88         }
89
90         return STATUS_SUCCESS;
91 }
92
93 /***************************************************************
94 * Function        - bcm_char_open()
95 *
96 * Description - This is the "open" entry point for the character
97 *                               driver.
98 *
99 * Parameters  - inode: Pointer to the Inode structure of char device
100 *                               filp : File pointer of the char device
101 *
102 * Returns         - Zero(Success)
103 ****************************************************************/
104
105 static int bcm_char_open(struct inode *inode, struct file *filp)
106 {
107         struct bcm_mini_adapter *ad = NULL;
108         struct bcm_tarang_data *tarang = NULL;
109
110         ad = GET_BCM_ADAPTER(gblpnetdev);
111         tarang = kzalloc(sizeof(struct bcm_tarang_data), GFP_KERNEL);
112         if (!tarang)
113                 return -ENOMEM;
114
115         tarang->Adapter = ad;
116         tarang->RxCntrlMsgBitMask = 0xFFFFFFFF & ~(1 << 0xB);
117
118         down(&ad->RxAppControlQueuelock);
119         tarang->next = ad->pTarangs;
120         ad->pTarangs = tarang;
121         up(&ad->RxAppControlQueuelock);
122
123         /* Store the Adapter structure */
124         filp->private_data = tarang;
125
126         /* Start Queuing the control response Packets */
127         atomic_inc(&ad->ApplicationRunning);
128
129         nonseekable_open(inode, filp);
130         return 0;
131 }
132
133 static int bcm_char_release(struct inode *inode, struct file *filp)
134 {
135         struct bcm_tarang_data *tarang, *tmp, *ptmp;
136         struct bcm_mini_adapter *ad = NULL;
137         struct sk_buff *pkt, *npkt;
138
139         tarang = (struct bcm_tarang_data *)filp->private_data;
140
141         if (tarang == NULL)
142                 return 0;
143
144         ad = tarang->Adapter;
145
146         down(&ad->RxAppControlQueuelock);
147
148         tmp = ad->pTarangs;
149         for (ptmp = NULL; tmp; ptmp = tmp, tmp = tmp->next) {
150                 if (tmp == tarang)
151                         break;
152         }
153
154         if (tmp) {
155                 if (!ptmp)
156                         ad->pTarangs = tmp->next;
157                 else
158                         ptmp->next = tmp->next;
159         } else {
160                 up(&ad->RxAppControlQueuelock);
161                 return 0;
162         }
163
164         pkt = tarang->RxAppControlHead;
165         while (pkt) {
166                 npkt = pkt->next;
167                 kfree_skb(pkt);
168                 pkt = npkt;
169         }
170
171         up(&ad->RxAppControlQueuelock);
172
173         /* Stop Queuing the control response Packets */
174         atomic_dec(&ad->ApplicationRunning);
175
176         kfree(tarang);
177
178         /* remove this filp from the asynchronously notified filp's */
179         filp->private_data = NULL;
180         return 0;
181 }
182
183 static ssize_t bcm_char_read(struct file *filp,
184                              char __user *buf,
185                              size_t size,
186                              loff_t *f_pos)
187 {
188         struct bcm_tarang_data *tarang = filp->private_data;
189         struct bcm_mini_adapter *ad = tarang->Adapter;
190         struct sk_buff *packet = NULL;
191         ssize_t pkt_len = 0;
192         int wait_ret_val = 0;
193         unsigned long ret = 0;
194
195         wait_ret_val = wait_event_interruptible(
196                                 ad->process_read_wait_queue,
197                                 (tarang->RxAppControlHead ||
198                                 ad->device_removed));
199
200         if ((wait_ret_val == -ERESTARTSYS)) {
201                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
202                                 "Exiting as i've been asked to exit!!!\n");
203                 return wait_ret_val;
204         }
205
206         if (ad->device_removed) {
207                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
208                                 "Device Removed... Killing the Apps...\n");
209                 return -ENODEV;
210         }
211
212         if (false == ad->fw_download_done)
213                 return -EACCES;
214
215         down(&ad->RxAppControlQueuelock);
216
217         if (tarang->RxAppControlHead) {
218                 packet = tarang->RxAppControlHead;
219                 DEQUEUEPACKET(tarang->RxAppControlHead,
220                               tarang->RxAppControlTail);
221                 tarang->AppCtrlQueueLen--;
222         }
223
224         up(&ad->RxAppControlQueuelock);
225
226         if (packet) {
227                 pkt_len = packet->len;
228                 ret = copy_to_user(buf, packet->data,
229                                    min_t(size_t, pkt_len, size));
230                 if (ret) {
231                         dev_kfree_skb(packet);
232                         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
233                                         "Returning from copy to user failure\n");
234                         return -EFAULT;
235                 }
236                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
237                                 "Read %zd Bytes From Adapter packet = %p by process %d!\n",
238                                 pkt_len, packet, current->pid);
239                 dev_kfree_skb(packet);
240         }
241
242         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "<\n");
243         return pkt_len;
244 }
245
246 static int bcm_char_ioctl_reg_read_private(void __user *argp,
247                                            struct bcm_mini_adapter *ad)
248 {
249         struct bcm_rdm_buffer rdm_buff = {0};
250         struct bcm_ioctl_buffer io_buff;
251         PCHAR temp_buff;
252         INT status = STATUS_FAILURE;
253         UINT buff_len;
254         u16 temp_value;
255         int bytes;
256
257         /* Copy Ioctl Buffer structure */
258         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
259                 return -EFAULT;
260
261         if (io_buff.InputLength > sizeof(rdm_buff))
262                 return -EINVAL;
263
264         if (copy_from_user(&rdm_buff, io_buff.InputBuffer,
265                 io_buff.InputLength))
266                 return -EFAULT;
267
268         if (io_buff.OutputLength > USHRT_MAX ||
269                 io_buff.OutputLength == 0) {
270                 return -EINVAL;
271         }
272
273         buff_len = io_buff.OutputLength;
274         temp_value = 4 - (buff_len % 4);
275         buff_len += temp_value % 4;
276
277         temp_buff = kmalloc(buff_len, GFP_KERNEL);
278         if (!temp_buff)
279                 return -ENOMEM;
280
281         bytes = rdmalt(ad, (UINT)rdm_buff.Register,
282                         (PUINT)temp_buff, buff_len);
283         if (bytes > 0) {
284                 status = STATUS_SUCCESS;
285                 if (copy_to_user(io_buff.OutputBuffer, temp_buff, bytes)) {
286                         kfree(temp_buff);
287                         return -EFAULT;
288                 }
289         } else {
290                 status = bytes;
291         }
292
293         kfree(temp_buff);
294         return status;
295 }
296
297 static int bcm_char_ioctl_reg_write_private(void __user *argp,
298                                             struct bcm_mini_adapter *ad)
299 {
300         struct bcm_wrm_buffer wrm_buff = {0};
301         struct bcm_ioctl_buffer io_buff;
302         UINT tmp = 0;
303         INT status;
304
305         /* Copy Ioctl Buffer structure */
306
307         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
308                 return -EFAULT;
309
310         if (io_buff.InputLength > sizeof(wrm_buff))
311                 return -EINVAL;
312
313         /* Get WrmBuffer structure */
314         if (copy_from_user(&wrm_buff, io_buff.InputBuffer,
315                 io_buff.InputLength))
316                 return -EFAULT;
317
318         tmp = wrm_buff.Register & EEPROM_REJECT_MASK;
319         if (!((ad->pstargetparams->m_u32Customize) & VSG_MODE) &&
320                 ((tmp == EEPROM_REJECT_REG_1) ||
321                         (tmp == EEPROM_REJECT_REG_2) ||
322                         (tmp == EEPROM_REJECT_REG_3) ||
323                         (tmp == EEPROM_REJECT_REG_4))) {
324
325                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
326                                 "EEPROM Access Denied, not in VSG Mode\n");
327                 return -EFAULT;
328         }
329
330         status = wrmalt(ad, (UINT)wrm_buff.Register,
331                         (PUINT)wrm_buff.Data, sizeof(ULONG));
332
333         if (status == STATUS_SUCCESS) {
334                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
335                                 DBG_LVL_ALL, "WRM Done\n");
336         } else {
337                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
338                                 DBG_LVL_ALL, "WRM Failed\n");
339                 status = -EFAULT;
340         }
341         return status;
342 }
343
344 static int bcm_char_ioctl_eeprom_reg_read(void __user *argp,
345                                           struct bcm_mini_adapter *ad)
346 {
347         struct bcm_rdm_buffer rdm_buff = {0};
348         struct bcm_ioctl_buffer io_buff;
349         PCHAR temp_buff = NULL;
350         UINT tmp = 0;
351         INT status;
352         int bytes;
353
354         if ((ad->IdleMode == TRUE) ||
355                 (ad->bShutStatus == TRUE) ||
356                 (ad->bPreparingForLowPowerMode == TRUE)) {
357
358                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
359                                 "Device in Idle Mode, Blocking Rdms\n");
360                 return -EACCES;
361         }
362
363         /* Copy Ioctl Buffer structure */
364         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
365                 return -EFAULT;
366
367         if (io_buff.InputLength > sizeof(rdm_buff))
368                 return -EINVAL;
369
370         if (copy_from_user(&rdm_buff, io_buff.InputBuffer,
371                 io_buff.InputLength))
372                 return -EFAULT;
373
374         if (io_buff.OutputLength > USHRT_MAX ||
375                 io_buff.OutputLength == 0) {
376                 return -EINVAL;
377         }
378
379         temp_buff = kmalloc(io_buff.OutputLength, GFP_KERNEL);
380         if (!temp_buff)
381                 return STATUS_FAILURE;
382
383         if ((((ULONG)rdm_buff.Register & 0x0F000000) != 0x0F000000) ||
384                 ((ULONG)rdm_buff.Register & 0x3)) {
385
386                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
387                                 "RDM Done On invalid Address : %x Access Denied.\n",
388                                 (int)rdm_buff.Register);
389
390                 kfree(temp_buff);
391                 return -EINVAL;
392         }
393
394         tmp = rdm_buff.Register & EEPROM_REJECT_MASK;
395         bytes = rdmaltWithLock(ad, (UINT)rdm_buff.Register,
396                                (PUINT)temp_buff, io_buff.OutputLength);
397
398         if (bytes > 0) {
399                 status = STATUS_SUCCESS;
400                 if (copy_to_user(io_buff.OutputBuffer, temp_buff, bytes)) {
401                         kfree(temp_buff);
402                         return -EFAULT;
403                 }
404         } else {
405                 status = bytes;
406         }
407
408         kfree(temp_buff);
409         return status;
410 }
411
412 static int bcm_char_ioctl_eeprom_reg_write(void __user *argp,
413                                            struct bcm_mini_adapter *ad,
414                                            UINT cmd)
415 {
416         struct bcm_wrm_buffer wrm_buff = {0};
417         struct bcm_ioctl_buffer io_buff;
418         UINT tmp = 0;
419         INT status;
420
421         if ((ad->IdleMode == TRUE) ||
422                 (ad->bShutStatus == TRUE) ||
423                 (ad->bPreparingForLowPowerMode == TRUE)) {
424
425                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
426                                 "Device in Idle Mode, Blocking Wrms\n");
427                 return -EACCES;
428         }
429
430         /* Copy Ioctl Buffer structure */
431         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
432                 return -EFAULT;
433
434         if (io_buff.InputLength > sizeof(wrm_buff))
435                 return -EINVAL;
436
437         /* Get WrmBuffer structure */
438         if (copy_from_user(&wrm_buff, io_buff.InputBuffer,
439                 io_buff.InputLength))
440                 return -EFAULT;
441
442         if ((((ULONG)wrm_buff.Register & 0x0F000000) != 0x0F000000) ||
443                 ((ULONG)wrm_buff.Register & 0x3)) {
444
445                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
446                                 "WRM Done On invalid Address : %x Access Denied.\n",
447                                 (int)wrm_buff.Register);
448                 return -EINVAL;
449         }
450
451         tmp = wrm_buff.Register & EEPROM_REJECT_MASK;
452         if (!((ad->pstargetparams->m_u32Customize) & VSG_MODE) &&
453                         ((tmp == EEPROM_REJECT_REG_1) ||
454                         (tmp == EEPROM_REJECT_REG_2) ||
455                         (tmp == EEPROM_REJECT_REG_3) ||
456                         (tmp == EEPROM_REJECT_REG_4)) &&
457                         (cmd == IOCTL_BCM_REGISTER_WRITE)) {
458
459                         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
460                                         "EEPROM Access Denied, not in VSG Mode\n");
461                         return -EFAULT;
462         }
463
464         status = wrmaltWithLock(ad, (UINT)wrm_buff.Register,
465                                 (PUINT)wrm_buff.Data,
466                                 wrm_buff.Length);
467
468         if (status == STATUS_SUCCESS) {
469                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, OSAL_DBG,
470                                 DBG_LVL_ALL, "WRM Done\n");
471         } else {
472                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
473                                 DBG_LVL_ALL, "WRM Failed\n");
474                 status = -EFAULT;
475         }
476         return status;
477 }
478
479 static int bcm_char_ioctl_gpio_set_request(void __user *argp,
480                                            struct bcm_mini_adapter *ad)
481 {
482         struct bcm_gpio_info gpio_info = {0};
483         struct bcm_ioctl_buffer io_buff;
484         UCHAR reset_val[4];
485         UINT value = 0;
486         UINT bit = 0;
487         UINT operation = 0;
488         INT status;
489         int bytes;
490
491         if ((ad->IdleMode == TRUE) ||
492                 (ad->bShutStatus == TRUE) ||
493                 (ad->bPreparingForLowPowerMode == TRUE)) {
494
495                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
496                                 DBG_LVL_ALL,
497                                 "GPIO Can't be set/clear in Low power Mode");
498                 return -EACCES;
499         }
500
501         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
502                 return -EFAULT;
503
504         if (io_buff.InputLength > sizeof(gpio_info))
505                 return -EINVAL;
506
507         if (copy_from_user(&gpio_info, io_buff.InputBuffer,
508                            io_buff.InputLength))
509                 return -EFAULT;
510
511         bit  = gpio_info.uiGpioNumber;
512         operation = gpio_info.uiGpioValue;
513         value = (1<<bit);
514
515         if (IsReqGpioIsLedInNVM(ad, value) == false) {
516                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
517                                 DBG_LVL_ALL,
518                                 "Sorry, Requested GPIO<0x%X> is not correspond to LED !!!",
519                                 value);
520                 return -EINVAL;
521         }
522
523         /* Set - setting 1 */
524         if (operation) {
525                 /* Set the gpio output register */
526                 status = wrmaltWithLock(ad,
527                                         BCM_GPIO_OUTPUT_SET_REG,
528                                         (PUINT)(&value), sizeof(UINT));
529
530                 if (status == STATUS_SUCCESS) {
531                         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS,
532                                         OSAL_DBG, DBG_LVL_ALL,
533                                         "Set the GPIO bit\n");
534                 } else {
535                         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS,
536                                         OSAL_DBG, DBG_LVL_ALL,
537                                         "Failed to set the %dth GPIO\n",
538                                         bit);
539                         return status;
540                 }
541         } else {
542                 /* Set the gpio output register */
543                 status = wrmaltWithLock(ad,
544                                         BCM_GPIO_OUTPUT_CLR_REG,
545                                         (PUINT)(&value), sizeof(UINT));
546
547                 if (status == STATUS_SUCCESS) {
548                         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS,
549                                         OSAL_DBG, DBG_LVL_ALL,
550                                         "Set the GPIO bit\n");
551                 } else {
552                         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS,
553                                         OSAL_DBG, DBG_LVL_ALL,
554                                         "Failed to clear the %dth GPIO\n",
555                                         bit);
556                         return status;
557                 }
558         }
559
560         bytes = rdmaltWithLock(ad, (UINT)GPIO_MODE_REGISTER,
561                                (PUINT)reset_val, sizeof(UINT));
562         if (bytes < 0) {
563                 status = bytes;
564                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
565                                 "GPIO_MODE_REGISTER read failed");
566                 return status;
567         }
568         status = STATUS_SUCCESS;
569
570         /* Set the gpio mode register to output */
571         *(UINT *)reset_val |= (1<<bit);
572         status = wrmaltWithLock(ad, GPIO_MODE_REGISTER,
573                                 (PUINT)reset_val, sizeof(UINT));
574
575         if (status == STATUS_SUCCESS) {
576                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
577                                 DBG_LVL_ALL,
578                                 "Set the GPIO to output Mode\n");
579         } else {
580                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
581                                 DBG_LVL_ALL,
582                                 "Failed to put GPIO in Output Mode\n");
583         }
584
585         return status;
586 }
587
588 static int bcm_char_ioctl_led_thread_state_change_req(void __user *argp,
589                 struct bcm_mini_adapter *ad)
590 {
591         struct bcm_user_thread_req thread_req = {0};
592         struct bcm_ioctl_buffer io_buff;
593
594         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
595                         "User made LED thread InActive");
596
597         if ((ad->IdleMode == TRUE) ||
598                 (ad->bShutStatus == TRUE) ||
599                 (ad->bPreparingForLowPowerMode == TRUE)) {
600
601                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
602                                 DBG_LVL_ALL,
603                                 "GPIO Can't be set/clear in Low power Mode");
604                 return -EACCES;
605         }
606
607         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
608                 return -EFAULT;
609
610         if (io_buff.InputLength > sizeof(thread_req))
611                 return -EINVAL;
612
613         if (copy_from_user(&thread_req, io_buff.InputBuffer,
614                            io_buff.InputLength))
615                 return -EFAULT;
616
617         /* if LED thread is running(Actively or Inactively)
618          * set it state to make inactive
619          */
620         if (ad->LEDInfo.led_thread_running) {
621                 if (thread_req.ThreadState == LED_THREAD_ACTIVATION_REQ) {
622                         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS,
623                                         OSAL_DBG, DBG_LVL_ALL,
624                                         "Activating thread req");
625                         ad->DriverState = LED_THREAD_ACTIVE;
626                 } else {
627                         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS,
628                                         OSAL_DBG, DBG_LVL_ALL,
629                                         "DeActivating Thread req.....");
630                         ad->DriverState = LED_THREAD_INACTIVE;
631                 }
632
633                 /* signal thread. */
634                 wake_up(&ad->LEDInfo.notify_led_event);
635         }
636         return STATUS_SUCCESS;
637 }
638
639 static int bcm_char_ioctl_gpio_status_request(void __user *argp,
640                                               struct bcm_mini_adapter *ad)
641 {
642         struct bcm_gpio_info gpio_info = {0};
643         struct bcm_ioctl_buffer io_buff;
644         ULONG bit = 0;
645         UCHAR read[4];
646         INT status;
647         int bytes;
648
649         if ((ad->IdleMode == TRUE) ||
650                 (ad->bShutStatus == TRUE) ||
651                 (ad->bPreparingForLowPowerMode == TRUE))
652                 return -EACCES;
653
654         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
655                 return -EFAULT;
656
657         if (io_buff.InputLength > sizeof(gpio_info))
658                 return -EINVAL;
659
660         if (copy_from_user(&gpio_info, io_buff.InputBuffer,
661                 io_buff.InputLength))
662                 return -EFAULT;
663
664         bit = gpio_info.uiGpioNumber;
665
666         /* Set the gpio output register */
667         bytes = rdmaltWithLock(ad, (UINT)GPIO_PIN_STATE_REGISTER,
668                                 (PUINT)read, sizeof(UINT));
669
670         if (bytes < 0) {
671                 status = bytes;
672                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
673                                 "RDM Failed\n");
674                 return status;
675         }
676         status = STATUS_SUCCESS;
677         return status;
678 }
679
680 static int bcm_char_ioctl_gpio_multi_request(void __user *argp,
681                                              struct bcm_mini_adapter *ad)
682 {
683         struct bcm_gpio_multi_info gpio_multi_info[MAX_IDX];
684         struct bcm_gpio_multi_info *pgpio_multi_info =
685                 (struct bcm_gpio_multi_info *)gpio_multi_info;
686         struct bcm_ioctl_buffer io_buff;
687         UCHAR reset_val[4];
688         INT status = STATUS_FAILURE;
689         int bytes;
690
691         memset(pgpio_multi_info, 0,
692                MAX_IDX * sizeof(struct bcm_gpio_multi_info));
693
694         if ((ad->IdleMode == TRUE) ||
695                 (ad->bShutStatus == TRUE) ||
696                 (ad->bPreparingForLowPowerMode == TRUE))
697                 return -EINVAL;
698
699         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
700                 return -EFAULT;
701
702         if (io_buff.InputLength > sizeof(gpio_multi_info))
703                 return -EINVAL;
704         if (io_buff.OutputLength > sizeof(gpio_multi_info))
705                 io_buff.OutputLength = sizeof(gpio_multi_info);
706
707         if (copy_from_user(&gpio_multi_info, io_buff.InputBuffer,
708                            io_buff.InputLength))
709                 return -EFAULT;
710
711         if (IsReqGpioIsLedInNVM(ad, pgpio_multi_info[WIMAX_IDX].uiGPIOMask)
712                         == false) {
713                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
714                                 DBG_LVL_ALL,
715                                 "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
716                                 pgpio_multi_info[WIMAX_IDX].uiGPIOMask,
717                                 ad->gpioBitMap);
718                 return -EINVAL;
719         }
720
721         /* Set the gpio output register */
722         if ((pgpio_multi_info[WIMAX_IDX].uiGPIOMask) &
723                 (pgpio_multi_info[WIMAX_IDX].uiGPIOCommand)) {
724                 /* Set 1's in GPIO OUTPUT REGISTER */
725                 *(UINT *)reset_val = pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
726                         pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
727                         pgpio_multi_info[WIMAX_IDX].uiGPIOValue;
728
729                 if (*(UINT *) reset_val)
730                         status = wrmaltWithLock(ad,
731                                 BCM_GPIO_OUTPUT_SET_REG,
732                                 (PUINT)reset_val, sizeof(ULONG));
733
734                 if (status != STATUS_SUCCESS) {
735                         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
736                                 "WRM to BCM_GPIO_OUTPUT_SET_REG Failed.");
737                         return status;
738                 }
739
740                 /* Clear to 0's in GPIO OUTPUT REGISTER */
741                 *(UINT *)reset_val =
742                         (pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
743                         pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
744                         (~(pgpio_multi_info[WIMAX_IDX].uiGPIOValue)));
745
746                 if (*(UINT *) reset_val)
747                         status = wrmaltWithLock(ad,
748                                 BCM_GPIO_OUTPUT_CLR_REG, (PUINT)reset_val,
749                                 sizeof(ULONG));
750
751                 if (status != STATUS_SUCCESS) {
752                         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
753                                         "WRM to BCM_GPIO_OUTPUT_CLR_REG Failed.");
754                         return status;
755                 }
756         }
757
758         if (pgpio_multi_info[WIMAX_IDX].uiGPIOMask) {
759                 bytes = rdmaltWithLock(ad, (UINT)GPIO_PIN_STATE_REGISTER,
760                                        (PUINT)reset_val, sizeof(UINT));
761
762                 if (bytes < 0) {
763                         status = bytes;
764                         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
765                                         "RDM to GPIO_PIN_STATE_REGISTER Failed.");
766                         return status;
767                 }
768                 status = STATUS_SUCCESS;
769
770                 pgpio_multi_info[WIMAX_IDX].uiGPIOValue =
771                         (*(UINT *)reset_val &
772                         pgpio_multi_info[WIMAX_IDX].uiGPIOMask);
773         }
774
775         status = copy_to_user(io_buff.OutputBuffer, &gpio_multi_info,
776                 io_buff.OutputLength);
777         if (status) {
778                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
779                         "Failed while copying Content to IOBufer for user space err:%d",
780                         status);
781                 return -EFAULT;
782         }
783         return status;
784 }
785
786 static int bcm_char_ioctl_gpio_mode_request(void __user *argp,
787                                             struct bcm_mini_adapter *ad)
788 {
789         struct bcm_gpio_multi_mode gpio_multi_mode[MAX_IDX];
790         struct bcm_gpio_multi_mode *pgpio_multi_mode =
791                 (struct bcm_gpio_multi_mode *)gpio_multi_mode;
792         struct bcm_ioctl_buffer io_buff;
793         UCHAR reset_val[4];
794         INT status;
795         int bytes;
796
797         if ((ad->IdleMode == TRUE) ||
798                 (ad->bShutStatus == TRUE) ||
799                 (ad->bPreparingForLowPowerMode == TRUE))
800                 return -EINVAL;
801
802         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
803                 return -EFAULT;
804
805         if (io_buff.InputLength > sizeof(gpio_multi_mode))
806                 return -EINVAL;
807         if (io_buff.OutputLength > sizeof(gpio_multi_mode))
808                 io_buff.OutputLength = sizeof(gpio_multi_mode);
809
810         if (copy_from_user(&gpio_multi_mode, io_buff.InputBuffer,
811                 io_buff.InputLength))
812                 return -EFAULT;
813
814         bytes = rdmaltWithLock(ad, (UINT)GPIO_MODE_REGISTER,
815                 (PUINT)reset_val, sizeof(UINT));
816
817         if (bytes < 0) {
818                 status = bytes;
819                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
820                         "Read of GPIO_MODE_REGISTER failed");
821                 return status;
822         }
823         status = STATUS_SUCCESS;
824
825         /* Validating the request */
826         if (IsReqGpioIsLedInNVM(ad, pgpio_multi_mode[WIMAX_IDX].uiGPIOMask)
827                         == false) {
828                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
829                                 "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
830                                 pgpio_multi_mode[WIMAX_IDX].uiGPIOMask,
831                                 ad->gpioBitMap);
832                 return -EINVAL;
833         }
834
835         if (pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) {
836                 /* write all OUT's (1's) */
837                 *(UINT *) reset_val |=
838                         (pgpio_multi_mode[WIMAX_IDX].uiGPIOMode &
839                                         pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
840
841                 /* write all IN's (0's) */
842                 *(UINT *) reset_val &=
843                         ~((~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) &
844                                         pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
845
846                 /* Currently implemented return the modes of all GPIO's
847                  * else needs to bit AND with  mask
848                  */
849                 pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)reset_val;
850
851                 status = wrmaltWithLock(ad, GPIO_MODE_REGISTER,
852                         (PUINT)reset_val, sizeof(ULONG));
853                 if (status == STATUS_SUCCESS) {
854                         BCM_DEBUG_PRINT(ad,
855                                 DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
856                                 "WRM to GPIO_MODE_REGISTER Done");
857                 } else {
858                         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
859                                         "WRM to GPIO_MODE_REGISTER Failed");
860                         return -EFAULT;
861                 }
862         } else {
863                 /* if uiGPIOMask is 0 then return mode register configuration */
864                 pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)reset_val;
865         }
866
867         status = copy_to_user(io_buff.OutputBuffer, &gpio_multi_mode,
868                 io_buff.OutputLength);
869         if (status) {
870                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
871                         "Failed while copying Content to IOBufer for user space err:%d",
872                         status);
873                 return -EFAULT;
874         }
875         return status;
876 }
877
878 static int bcm_char_ioctl_misc_request(void __user *argp,
879                                        struct bcm_mini_adapter *ad)
880 {
881         struct bcm_ioctl_buffer io_buff;
882         PVOID buff = NULL;
883         INT status;
884
885         /* Copy Ioctl Buffer structure */
886         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
887                 return -EFAULT;
888
889         if (io_buff.InputLength < sizeof(struct bcm_link_request))
890                 return -EINVAL;
891
892         if (io_buff.InputLength > MAX_CNTL_PKT_SIZE)
893                 return -EINVAL;
894
895         buff = memdup_user(io_buff.InputBuffer,
896                                io_buff.InputLength);
897         if (IS_ERR(buff))
898                 return PTR_ERR(buff);
899
900         down(&ad->LowPowerModeSync);
901         status = wait_event_interruptible_timeout(
902                         ad->lowpower_mode_wait_queue,
903                         !ad->bPreparingForLowPowerMode,
904                         (1 * HZ));
905
906         if (status == -ERESTARTSYS)
907                 goto cntrlEnd;
908
909         if (ad->bPreparingForLowPowerMode) {
910                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
911                                 "Preparing Idle Mode is still True - Hence Rejecting control message\n");
912                 status = STATUS_FAILURE;
913                 goto cntrlEnd;
914         }
915         status = CopyBufferToControlPacket(ad, (PVOID)buff);
916
917 cntrlEnd:
918         up(&ad->LowPowerModeSync);
919         kfree(buff);
920         return status;
921 }
922
923 static int bcm_char_ioctl_buffer_download_start(
924                 struct bcm_mini_adapter *ad)
925 {
926         INT status;
927
928         if (down_trylock(&ad->NVMRdmWrmLock)) {
929                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
930                                 "IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
931                 return -EACCES;
932         }
933
934         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
935                         "Starting the firmware download PID =0x%x!!!!\n",
936                         current->pid);
937
938         if (down_trylock(&ad->fw_download_sema))
939                 return -EBUSY;
940
941         ad->bBinDownloaded = false;
942         ad->fw_download_process_pid = current->pid;
943         ad->bCfgDownloaded = false;
944         ad->fw_download_done = false;
945         netif_carrier_off(ad->dev);
946         netif_stop_queue(ad->dev);
947         status = reset_card_proc(ad);
948         if (status) {
949                 pr_err(PFX "%s: reset_card_proc Failed!\n", ad->dev->name);
950                 up(&ad->fw_download_sema);
951                 up(&ad->NVMRdmWrmLock);
952                 return status;
953         }
954         mdelay(10);
955
956         up(&ad->NVMRdmWrmLock);
957         return status;
958 }
959
960 static int bcm_char_ioctl_buffer_download(void __user *argp,
961                                           struct bcm_mini_adapter *ad)
962 {
963         struct bcm_firmware_info *fw_info = NULL;
964         struct bcm_ioctl_buffer io_buff;
965         INT status;
966
967         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
968                 "Starting the firmware download PID =0x%x!!!!\n", current->pid);
969
970         if (!down_trylock(&ad->fw_download_sema)) {
971                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
972                                 "Invalid way to download buffer. Use Start and then call this!!!\n");
973                 up(&ad->fw_download_sema);
974                 return -EINVAL;
975         }
976
977         /* Copy Ioctl Buffer structure */
978         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer))) {
979                 up(&ad->fw_download_sema);
980                 return -EFAULT;
981         }
982
983         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
984                         "Length for FW DLD is : %lx\n", io_buff.InputLength);
985
986         if (io_buff.InputLength > sizeof(struct bcm_firmware_info)) {
987                 up(&ad->fw_download_sema);
988                 return -EINVAL;
989         }
990
991         fw_info = kmalloc(sizeof(*fw_info), GFP_KERNEL);
992         if (!fw_info) {
993                 up(&ad->fw_download_sema);
994                 return -ENOMEM;
995         }
996
997         if (copy_from_user(fw_info, io_buff.InputBuffer,
998                 io_buff.InputLength)) {
999                 up(&ad->fw_download_sema);
1000                 kfree(fw_info);
1001                 return -EFAULT;
1002         }
1003
1004         if (!fw_info->pvMappedFirmwareAddress ||
1005                 (fw_info->u32FirmwareLength == 0)) {
1006
1007                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1008                                 "Something else is wrong %lu\n",
1009                                 fw_info->u32FirmwareLength);
1010                 up(&ad->fw_download_sema);
1011                 kfree(fw_info);
1012                 status = -EINVAL;
1013                 return status;
1014         }
1015
1016         status = bcm_ioctl_fw_download(ad, fw_info);
1017
1018         if (status != STATUS_SUCCESS) {
1019                 if (fw_info->u32StartingAddress == CONFIG_BEGIN_ADDR)
1020                         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1021                                 "IOCTL: Configuration File Upload Failed\n");
1022                 else
1023                         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1024                                 "IOCTL: Firmware File Upload Failed\n");
1025
1026                 /* up(&ad->fw_download_sema); */
1027
1028                 if (ad->LEDInfo.led_thread_running &
1029                         BCM_LED_THREAD_RUNNING_ACTIVELY) {
1030                         ad->DriverState = DRIVER_INIT;
1031                         ad->LEDInfo.bLedInitDone = false;
1032                         wake_up(&ad->LEDInfo.notify_led_event);
1033                 }
1034         }
1035
1036         if (status != STATUS_SUCCESS)
1037                 up(&ad->fw_download_sema);
1038
1039         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL,
1040                 "IOCTL: Firmware File Uploaded\n");
1041         kfree(fw_info);
1042         return status;
1043 }
1044
1045 static int bcm_char_ioctl_buffer_download_stop(void __user *argp,
1046                                                struct bcm_mini_adapter *ad)
1047 {
1048         INT status;
1049         int timeout = 0;
1050
1051         if (!down_trylock(&ad->fw_download_sema)) {
1052                 up(&ad->fw_download_sema);
1053                 return -EINVAL;
1054         }
1055
1056         if (down_trylock(&ad->NVMRdmWrmLock)) {
1057                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1058                                 "FW download blocked as EEPROM Read/Write is in progress\n");
1059                 up(&ad->fw_download_sema);
1060                 return -EACCES;
1061         }
1062
1063         ad->bBinDownloaded = TRUE;
1064         ad->bCfgDownloaded = TRUE;
1065         atomic_set(&ad->CurrNumFreeTxDesc, 0);
1066         ad->CurrNumRecvDescs = 0;
1067         ad->downloadDDR = 0;
1068
1069         /* setting the Mips to Run */
1070         status = run_card_proc(ad);
1071
1072         if (status) {
1073                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1074                         "Firm Download Failed\n");
1075                 up(&ad->fw_download_sema);
1076                 up(&ad->NVMRdmWrmLock);
1077                 return status;
1078         }
1079         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
1080                         DBG_LVL_ALL, "Firm Download Over...\n");
1081
1082         mdelay(10);
1083
1084         /* Wait for MailBox Interrupt */
1085         if (StartInterruptUrb((struct bcm_interface_adapter *)ad->pvInterfaceAdapter))
1086                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1087                         "Unable to send interrupt...\n");
1088
1089         timeout = 5*HZ;
1090         ad->waiting_to_fw_download_done = false;
1091         wait_event_timeout(ad->ioctl_fw_dnld_wait_queue,
1092                         ad->waiting_to_fw_download_done, timeout);
1093         ad->fw_download_process_pid = INVALID_PID;
1094         ad->fw_download_done = TRUE;
1095         atomic_set(&ad->CurrNumFreeTxDesc, 0);
1096         ad->CurrNumRecvDescs = 0;
1097         ad->PrevNumRecvDescs = 0;
1098         atomic_set(&ad->cntrlpktCnt, 0);
1099         ad->LinkUpStatus = 0;
1100         ad->LinkStatus = 0;
1101
1102         if (ad->LEDInfo.led_thread_running &
1103                 BCM_LED_THREAD_RUNNING_ACTIVELY) {
1104                 ad->DriverState = FW_DOWNLOAD_DONE;
1105                 wake_up(&ad->LEDInfo.notify_led_event);
1106         }
1107
1108         if (!timeout)
1109                 status = -ENODEV;
1110
1111         up(&ad->fw_download_sema);
1112         up(&ad->NVMRdmWrmLock);
1113         return status;
1114 }
1115
1116 static int bcm_char_ioctl_chip_reset(struct bcm_mini_adapter *ad)
1117 {
1118         INT status;
1119         INT nvm_access;
1120
1121         nvm_access = down_trylock(&ad->NVMRdmWrmLock);
1122         if (nvm_access) {
1123                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1124                         " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
1125                 return -EACCES;
1126         }
1127
1128         down(&ad->RxAppControlQueuelock);
1129         status = reset_card_proc(ad);
1130         flushAllAppQ();
1131         up(&ad->RxAppControlQueuelock);
1132         up(&ad->NVMRdmWrmLock);
1133         ResetCounters(ad);
1134         return status;
1135 }
1136
1137 static int bcm_char_ioctl_qos_threshold(ULONG arg,
1138                                         struct bcm_mini_adapter *ad)
1139 {
1140         USHORT i;
1141
1142         for (i = 0; i < NO_OF_QUEUES; i++) {
1143                 if (get_user(ad->PackInfo[i].uiThreshold,
1144                                 (unsigned long __user *)arg)) {
1145                         return -EFAULT;
1146                 }
1147         }
1148         return 0;
1149 }
1150
1151 static int bcm_char_ioctl_switch_transfer_mode(void __user *argp,
1152                                                struct bcm_mini_adapter *ad)
1153 {
1154         UINT data = 0;
1155
1156         if (copy_from_user(&data, argp, sizeof(UINT)))
1157                 return -EFAULT;
1158
1159         if (data) {
1160                 /* Allow All Packets */
1161                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1162                         "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n");
1163                         ad->TransferMode = ETH_PACKET_TUNNELING_MODE;
1164         } else {
1165                 /* Allow IP only Packets */
1166                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1167                         "IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n");
1168                 ad->TransferMode = IP_PACKET_ONLY_MODE;
1169         }
1170         return STATUS_SUCCESS;
1171 }
1172
1173 static int bcm_char_ioctl_get_driver_version(void __user *argp)
1174 {
1175         struct bcm_ioctl_buffer io_buff;
1176         ulong len;
1177
1178         /* Copy Ioctl Buffer structure */
1179         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1180                 return -EFAULT;
1181
1182         len = min_t(ulong, io_buff.OutputLength, strlen(DRV_VERSION) + 1);
1183
1184         if (copy_to_user(io_buff.OutputBuffer, DRV_VERSION, len))
1185                 return -EFAULT;
1186
1187         return STATUS_SUCCESS;
1188 }
1189
1190 static int bcm_char_ioctl_get_current_status(void __user *argp,
1191                                              struct bcm_mini_adapter *ad)
1192 {
1193         struct bcm_link_state link_state;
1194         struct bcm_ioctl_buffer io_buff;
1195
1196         /* Copy Ioctl Buffer structure */
1197         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer))) {
1198                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1199                         "copy_from_user failed..\n");
1200                 return -EFAULT;
1201         }
1202
1203         if (io_buff.OutputLength != sizeof(link_state))
1204                 return -EINVAL;
1205
1206         memset(&link_state, 0, sizeof(link_state));
1207         link_state.bIdleMode = ad->IdleMode;
1208         link_state.bShutdownMode = ad->bShutStatus;
1209         link_state.ucLinkStatus = ad->LinkStatus;
1210
1211         if (copy_to_user(io_buff.OutputBuffer, &link_state, min_t(size_t,
1212                 sizeof(link_state), io_buff.OutputLength))) {
1213                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1214                         "Copy_to_user Failed..\n");
1215                 return -EFAULT;
1216         }
1217         return STATUS_SUCCESS;
1218 }
1219
1220
1221 static int bcm_char_ioctl_set_mac_tracing(void __user *argp,
1222                                           struct bcm_mini_adapter *ad)
1223 {
1224         struct bcm_ioctl_buffer io_buff;
1225         UINT tracing_flag;
1226
1227         /* copy ioctl Buffer structure */
1228         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1229                 return -EFAULT;
1230
1231         if (copy_from_user(&tracing_flag, io_buff.InputBuffer, sizeof(UINT)))
1232                 return -EFAULT;
1233
1234         if (tracing_flag)
1235                 ad->pTarangs->MacTracingEnabled = TRUE;
1236         else
1237                 ad->pTarangs->MacTracingEnabled = false;
1238
1239         return STATUS_SUCCESS;
1240 }
1241
1242 static int bcm_char_ioctl_get_dsx_indication(void __user *argp,
1243                                              struct bcm_mini_adapter *ad)
1244 {
1245         struct bcm_ioctl_buffer io_buff;
1246         ULONG sf_id = 0;
1247
1248         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1249                 return -EFAULT;
1250
1251         if (io_buff.OutputLength < sizeof(struct bcm_add_indication_alt)) {
1252                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1253                         "Mismatch req: %lx needed is =0x%zx!!!",
1254                         io_buff.OutputLength,
1255                         sizeof(struct bcm_add_indication_alt));
1256                 return -EINVAL;
1257         }
1258
1259         if (copy_from_user(&sf_id, io_buff.InputBuffer, sizeof(sf_id)))
1260                 return -EFAULT;
1261
1262         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1263                 "Get DSX Data SF ID is =%lx\n", sf_id);
1264         get_dsx_sf_data_to_application(ad, sf_id, io_buff.OutputBuffer);
1265         return STATUS_SUCCESS;
1266 }
1267
1268 static int bcm_char_ioctl_get_host_mibs(void __user *argp,
1269                                         struct bcm_mini_adapter *ad,
1270                                         struct bcm_tarang_data *tarang)
1271 {
1272         struct bcm_ioctl_buffer io_buff;
1273         INT status = STATUS_FAILURE;
1274         PVOID temp_buff;
1275
1276         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1277                 return -EFAULT;
1278
1279         if (io_buff.OutputLength != sizeof(struct bcm_host_stats_mibs)) {
1280                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1281                         "Length Check failed %lu %zd\n", io_buff.OutputLength,
1282                         sizeof(struct bcm_host_stats_mibs));
1283                 return -EINVAL;
1284         }
1285
1286         /* FIXME: HOST_STATS are too big for kmalloc (122048)! */
1287         temp_buff = kzalloc(sizeof(struct bcm_host_stats_mibs), GFP_KERNEL);
1288         if (!temp_buff)
1289                 return STATUS_FAILURE;
1290
1291         status = ProcessGetHostMibs(ad, temp_buff);
1292         GetDroppedAppCntrlPktMibs(temp_buff, tarang);
1293
1294         if (status != STATUS_FAILURE) {
1295                 if (copy_to_user(io_buff.OutputBuffer, temp_buff,
1296                         sizeof(struct bcm_host_stats_mibs))) {
1297                         kfree(temp_buff);
1298                         return -EFAULT;
1299                 }
1300         }
1301
1302         kfree(temp_buff);
1303         return status;
1304 }
1305
1306 static int bcm_char_ioctl_bulk_wrm(void __user *argp,
1307                                    struct bcm_mini_adapter *ad, UINT cmd)
1308 {
1309         struct bcm_bulk_wrm_buffer *bulk_buff;
1310         struct bcm_ioctl_buffer io_buff;
1311         UINT tmp = 0;
1312         INT status = STATUS_FAILURE;
1313         PCHAR buff = NULL;
1314
1315         if ((ad->IdleMode == TRUE) ||
1316                 (ad->bShutStatus == TRUE) ||
1317                 (ad->bPreparingForLowPowerMode == TRUE)) {
1318
1319                 BCM_DEBUG_PRINT (ad, DBG_TYPE_PRINTK, 0, 0,
1320                         "Device in Idle/Shutdown Mode, Blocking Wrms\n");
1321                 return -EACCES;
1322         }
1323
1324         /* Copy Ioctl Buffer structure */
1325         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1326                 return -EFAULT;
1327
1328         if (io_buff.InputLength < sizeof(ULONG) * 2)
1329                 return -EINVAL;
1330
1331         buff = memdup_user(io_buff.InputBuffer,
1332                                io_buff.InputLength);
1333         if (IS_ERR(buff))
1334                 return PTR_ERR(buff);
1335
1336         bulk_buff = (struct bcm_bulk_wrm_buffer *)buff;
1337
1338         if (((ULONG)bulk_buff->Register & 0x0F000000) != 0x0F000000 ||
1339                 ((ULONG)bulk_buff->Register & 0x3)) {
1340                 BCM_DEBUG_PRINT (ad, DBG_TYPE_PRINTK, 0, 0,
1341                         "WRM Done On invalid Address : %x Access Denied.\n",
1342                         (int)bulk_buff->Register);
1343                 kfree(buff);
1344                 return -EINVAL;
1345         }
1346
1347         tmp = bulk_buff->Register & EEPROM_REJECT_MASK;
1348         if (!((ad->pstargetparams->m_u32Customize)&VSG_MODE) &&
1349                 ((tmp == EEPROM_REJECT_REG_1) ||
1350                         (tmp == EEPROM_REJECT_REG_2) ||
1351                         (tmp == EEPROM_REJECT_REG_3) ||
1352                         (tmp == EEPROM_REJECT_REG_4)) &&
1353                 (cmd == IOCTL_BCM_REGISTER_WRITE)) {
1354
1355                 kfree(buff);
1356                 BCM_DEBUG_PRINT (ad, DBG_TYPE_PRINTK, 0, 0,
1357                         "EEPROM Access Denied, not in VSG Mode\n");
1358                 return -EFAULT;
1359         }
1360
1361         if (bulk_buff->SwapEndian == false)
1362                 status = wrmWithLock(ad, (UINT)bulk_buff->Register,
1363                         (PCHAR)bulk_buff->Values,
1364                         io_buff.InputLength - 2*sizeof(ULONG));
1365         else
1366                 status = wrmaltWithLock(ad, (UINT)bulk_buff->Register,
1367                         (PUINT)bulk_buff->Values,
1368                         io_buff.InputLength - 2*sizeof(ULONG));
1369
1370         if (status != STATUS_SUCCESS)
1371                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n");
1372
1373         kfree(buff);
1374         return status;
1375 }
1376
1377 static int bcm_char_ioctl_get_nvm_size(void __user *argp,
1378                                        struct bcm_mini_adapter *ad)
1379 {
1380         struct bcm_ioctl_buffer io_buff;
1381
1382         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1383                 return -EFAULT;
1384
1385         if (ad->eNVMType == NVM_EEPROM || ad->eNVMType == NVM_FLASH) {
1386                 if (copy_to_user(io_buff.OutputBuffer, &ad->uiNVMDSDSize,
1387                         sizeof(UINT)))
1388                         return -EFAULT;
1389         }
1390
1391         return STATUS_SUCCESS;
1392 }
1393
1394 static int bcm_char_ioctl_cal_init(void __user *argp,
1395                                    struct bcm_mini_adapter *ad)
1396 {
1397         struct bcm_ioctl_buffer io_buff;
1398         UINT sector_size = 0;
1399         INT status = STATUS_FAILURE;
1400
1401         if (ad->eNVMType == NVM_FLASH) {
1402                 if (copy_from_user(&io_buff, argp,
1403                         sizeof(struct bcm_ioctl_buffer)))
1404                         return -EFAULT;
1405
1406                 if (copy_from_user(&sector_size, io_buff.InputBuffer,
1407                         sizeof(UINT)))
1408                         return -EFAULT;
1409
1410                 if ((sector_size < MIN_SECTOR_SIZE) ||
1411                         (sector_size > MAX_SECTOR_SIZE)) {
1412                         if (copy_to_user(io_buff.OutputBuffer,
1413                                 &ad->uiSectorSize, sizeof(UINT)))
1414                                 return -EFAULT;
1415                 } else {
1416                         if (IsFlash2x(ad)) {
1417                                 if (copy_to_user(io_buff.OutputBuffer,
1418                                         &ad->uiSectorSize, sizeof(UINT)))
1419                                         return -EFAULT;
1420                         } else {
1421                                 if ((TRUE == ad->bShutStatus) ||
1422                                         (TRUE == ad->IdleMode)) {
1423                                         BCM_DEBUG_PRINT(ad,
1424                                                 DBG_TYPE_PRINTK, 0, 0,
1425                                                 "Device is in Idle/Shutdown Mode\n");
1426                                         return -EACCES;
1427                                 }
1428
1429                                 ad->uiSectorSize = sector_size;
1430                                 BcmUpdateSectorSize(ad,
1431                                         ad->uiSectorSize);
1432                         }
1433                 }
1434                 status = STATUS_SUCCESS;
1435         } else {
1436                 status = STATUS_FAILURE;
1437         }
1438         return status;
1439 }
1440
1441 static int bcm_char_ioctl_set_debug(void __user *argp,
1442                                     struct bcm_mini_adapter *ad)
1443 {
1444 #ifdef DEBUG
1445         struct bcm_ioctl_buffer io_buff;
1446         struct bcm_user_debug_state user_debug_state;
1447
1448         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1449                 "In SET_DEBUG ioctl\n");
1450         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1451                 return -EFAULT;
1452
1453         if (copy_from_user(&user_debug_state, io_buff.InputBuffer,
1454                 sizeof(struct bcm_user_debug_state)))
1455                 return -EFAULT;
1456
1457         BCM_DEBUG_PRINT (ad, DBG_TYPE_PRINTK, 0, 0,
1458                         "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ",
1459                         user_debug_state.OnOff, user_debug_state.Type);
1460         /* user_debug_state.Subtype <<= 1; */
1461         user_debug_state.Subtype = 1 << user_debug_state.Subtype;
1462         BCM_DEBUG_PRINT (ad, DBG_TYPE_PRINTK, 0, 0,
1463                 "actual Subtype=0x%x\n", user_debug_state.Subtype);
1464
1465         /* Update new 'DebugState' in the ad */
1466         ad->stDebugState.type |= user_debug_state.Type;
1467         /* Subtype: A bitmap of 32 bits for Subtype per Type.
1468          * Valid indexes in 'subtype' array: 1,2,4,8
1469          * corresponding to valid Type values. Hence we can use the 'Type' field
1470          * as the index value, ignoring the array entries 0,3,5,6,7 !
1471          */
1472         if (user_debug_state.OnOff)
1473                 ad->stDebugState.subtype[user_debug_state.Type] |=
1474                         user_debug_state.Subtype;
1475         else
1476                 ad->stDebugState.subtype[user_debug_state.Type] &=
1477                         ~user_debug_state.Subtype;
1478
1479         BCM_SHOW_DEBUG_BITMAP(ad);
1480 #endif
1481         return STATUS_SUCCESS;
1482 }
1483
1484 static int bcm_char_ioctl_nvm_rw(void __user *argp,
1485                                  struct bcm_mini_adapter *ad, UINT cmd)
1486 {
1487         struct bcm_nvm_readwrite nvm_rw;
1488         struct timeval tv0, tv1;
1489         struct bcm_ioctl_buffer io_buff;
1490         PUCHAR read_data = NULL;
1491         INT status = STATUS_FAILURE;
1492
1493         memset(&tv0, 0, sizeof(struct timeval));
1494         memset(&tv1, 0, sizeof(struct timeval));
1495         if ((ad->eNVMType == NVM_FLASH) &&
1496                 (ad->uiFlashLayoutMajorVersion == 0)) {
1497                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1498                         "The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n");
1499                 return -EFAULT;
1500         }
1501
1502         if (IsFlash2x(ad)) {
1503                 if ((ad->eActiveDSD != DSD0) &&
1504                         (ad->eActiveDSD != DSD1) &&
1505                         (ad->eActiveDSD != DSD2)) {
1506
1507                         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1508                                 "No DSD is active..hence NVM Command is blocked");
1509                         return STATUS_FAILURE;
1510                 }
1511         }
1512
1513         /* Copy Ioctl Buffer structure */
1514         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1515                 return -EFAULT;
1516
1517         if (copy_from_user(&nvm_rw,
1518                                 (IOCTL_BCM_NVM_READ == cmd) ?
1519                                 io_buff.OutputBuffer : io_buff.InputBuffer,
1520                                 sizeof(struct bcm_nvm_readwrite)))
1521                 return -EFAULT;
1522
1523         /*
1524          * Deny the access if the offset crosses the cal area limit.
1525          */
1526         if (nvm_rw.uiNumBytes > ad->uiNVMDSDSize)
1527                 return STATUS_FAILURE;
1528
1529         if (nvm_rw.uiOffset >
1530                 ad->uiNVMDSDSize - nvm_rw.uiNumBytes)
1531                 return STATUS_FAILURE;
1532
1533         read_data = memdup_user(nvm_rw.pBuffer,
1534                                 nvm_rw.uiNumBytes);
1535         if (IS_ERR(read_data))
1536                 return PTR_ERR(read_data);
1537
1538         do_gettimeofday(&tv0);
1539         if (IOCTL_BCM_NVM_READ == cmd) {
1540                 int ret = bcm_handle_nvm_read_cmd(ad, read_data,
1541                                 &nvm_rw);
1542                 if (ret != STATUS_SUCCESS)
1543                         return ret;
1544         } else {
1545                 down(&ad->NVMRdmWrmLock);
1546
1547                 if ((ad->IdleMode == TRUE) ||
1548                         (ad->bShutStatus == TRUE) ||
1549                         (ad->bPreparingForLowPowerMode == TRUE)) {
1550
1551                         BCM_DEBUG_PRINT(ad,
1552                                 DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1553                                 "Device is in Idle/Shutdown Mode\n");
1554                         up(&ad->NVMRdmWrmLock);
1555                         kfree(read_data);
1556                         return -EACCES;
1557                 }
1558
1559                 ad->bHeaderChangeAllowed = TRUE;
1560                 if (IsFlash2x(ad)) {
1561                         int ret = handle_flash2x_adapter(ad,
1562                                                         read_data,
1563                                                         &nvm_rw);
1564                         if (ret != STATUS_SUCCESS)
1565                                 return ret;
1566                 }
1567
1568                 status = BeceemNVMWrite(ad, (PUINT)read_data,
1569                         nvm_rw.uiOffset, nvm_rw.uiNumBytes,
1570                         nvm_rw.bVerify);
1571                 if (IsFlash2x(ad))
1572                         BcmFlash2xWriteSig(ad, ad->eActiveDSD);
1573
1574                 ad->bHeaderChangeAllowed = false;
1575
1576                 up(&ad->NVMRdmWrmLock);
1577
1578                 if (status != STATUS_SUCCESS) {
1579                         kfree(read_data);
1580                         return status;
1581                 }
1582         }
1583
1584         do_gettimeofday(&tv1);
1585         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1586                 " timetaken by Write/read :%ld msec\n",
1587                 (tv1.tv_sec - tv0.tv_sec)*1000 +
1588                 (tv1.tv_usec - tv0.tv_usec)/1000);
1589
1590         kfree(read_data);
1591         return STATUS_SUCCESS;
1592 }
1593
1594 static int bcm_char_ioctl_flash2x_section_read(void __user *argp,
1595         struct bcm_mini_adapter *ad)
1596 {
1597         struct bcm_flash2x_readwrite flash_2x_read = {0};
1598         struct bcm_ioctl_buffer io_buff;
1599         PUCHAR read_buff = NULL;
1600         UINT nob = 0;
1601         UINT buff_size = 0;
1602         UINT read_bytes = 0;
1603         UINT read_offset = 0;
1604         INT status = STATUS_FAILURE;
1605         void __user *OutPutBuff;
1606
1607         if (IsFlash2x(ad) != TRUE)      {
1608                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1609                         "Flash Does not have 2.x map");
1610                 return -EINVAL;
1611         }
1612
1613         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
1614                 DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called");
1615         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1616                 return -EFAULT;
1617
1618         /* Reading FLASH 2.x READ structure */
1619         if (copy_from_user(&flash_2x_read, io_buff.InputBuffer,
1620                 sizeof(struct bcm_flash2x_readwrite)))
1621                 return -EFAULT;
1622
1623         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1624                         "\nflash_2x_read.Section :%x",
1625                         flash_2x_read.Section);
1626         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1627                         "\nflash_2x_read.offset :%x",
1628                         flash_2x_read.offset);
1629         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1630                         "\nflash_2x_read.numOfBytes :%x",
1631                         flash_2x_read.numOfBytes);
1632         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1633                         "\nflash_2x_read.bVerify :%x\n",
1634                         flash_2x_read.bVerify);
1635
1636         /* This was internal to driver for raw read.
1637          * now it has ben exposed to user space app.
1638          */
1639         if (validateFlash2xReadWrite(ad, &flash_2x_read) == false)
1640                 return STATUS_FAILURE;
1641
1642         nob = flash_2x_read.numOfBytes;
1643         if (nob > ad->uiSectorSize)
1644                 buff_size = ad->uiSectorSize;
1645         else
1646                 buff_size = nob;
1647
1648         read_offset = flash_2x_read.offset;
1649         OutPutBuff = io_buff.OutputBuffer;
1650         read_buff = kzalloc(buff_size , GFP_KERNEL);
1651
1652         if (read_buff == NULL) {
1653                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1654                                 "Memory allocation failed for Flash 2.x Read Structure");
1655                 return -ENOMEM;
1656         }
1657         down(&ad->NVMRdmWrmLock);
1658
1659         if ((ad->IdleMode == TRUE) ||
1660                 (ad->bShutStatus == TRUE) ||
1661                 (ad->bPreparingForLowPowerMode == TRUE)) {
1662
1663                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG,
1664                                 DBG_LVL_ALL,
1665                                 "Device is in Idle/Shutdown Mode\n");
1666                 up(&ad->NVMRdmWrmLock);
1667                 kfree(read_buff);
1668                 return -EACCES;
1669         }
1670
1671         while (nob) {
1672                 if (nob > ad->uiSectorSize)
1673                         read_bytes = ad->uiSectorSize;
1674                 else
1675                         read_bytes = nob;
1676
1677                 /* Reading the data from Flash 2.x */
1678                 status = BcmFlash2xBulkRead(ad, (PUINT)read_buff,
1679                         flash_2x_read.Section, read_offset, read_bytes);
1680                 if (status) {
1681                         BCM_DEBUG_PRINT(ad,
1682                                 DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1683                                 "Flash 2x read err with status :%d",
1684                                 status);
1685                         break;
1686                 }
1687
1688                 BCM_DEBUG_PRINT_BUFFER(ad, DBG_TYPE_OTHERS, OSAL_DBG,
1689                         DBG_LVL_ALL, read_buff, read_bytes);
1690
1691                 status = copy_to_user(OutPutBuff, read_buff, read_bytes);
1692                 if (status) {
1693                         BCM_DEBUG_PRINT(ad,
1694                                 DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1695                                 "Copy to use failed with status :%d", status);
1696                         up(&ad->NVMRdmWrmLock);
1697                         kfree(read_buff);
1698                         return -EFAULT;
1699                 }
1700                 nob = nob - read_bytes;
1701                 if (nob) {
1702                         read_offset = read_offset + read_bytes;
1703                         OutPutBuff = OutPutBuff + read_bytes;
1704                 }
1705         }
1706
1707         up(&ad->NVMRdmWrmLock);
1708         kfree(read_buff);
1709         return status;
1710 }
1711
1712 static int bcm_char_ioctl_flash2x_section_write(void __user *argp,
1713         struct bcm_mini_adapter *ad)
1714 {
1715         struct bcm_flash2x_readwrite sFlash2xWrite = {0};
1716         struct bcm_ioctl_buffer io_buff;
1717         PUCHAR write_buff;
1718         void __user *input_addr;
1719         UINT nob = 0;
1720         UINT buff_size = 0;
1721         UINT write_off = 0;
1722         UINT write_bytes = 0;
1723         INT status = STATUS_FAILURE;
1724
1725         if (IsFlash2x(ad) != TRUE) {
1726                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1727                         "Flash Does not have 2.x map");
1728                 return -EINVAL;
1729         }
1730
1731         /* First make this False so that we can enable the Sector
1732          * Permission Check in BeceemFlashBulkWrite
1733          */
1734         ad->bAllDSDWriteAllow = false;
1735
1736         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1737                 "IOCTL_BCM_FLASH2X_SECTION_WRITE Called");
1738
1739         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1740                 return -EFAULT;
1741
1742         /* Reading FLASH 2.x READ structure */
1743         if (copy_from_user(&sFlash2xWrite, io_buff.InputBuffer,
1744                 sizeof(struct bcm_flash2x_readwrite)))
1745                 return -EFAULT;
1746
1747         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1748                 "\nsFlash2xWrite.Section :%x", sFlash2xWrite.Section);
1749         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1750                 "\nsFlash2xWrite.offset :%d", sFlash2xWrite.offset);
1751         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1752                 "\nsFlash2xWrite.numOfBytes :%x", sFlash2xWrite.numOfBytes);
1753         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1754                 "\nsFlash2xWrite.bVerify :%x\n", sFlash2xWrite.bVerify);
1755
1756         if ((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1)
1757                 && (sFlash2xWrite.Section != VSA2)) {
1758                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1759                         "Only VSA write is allowed");
1760                 return -EINVAL;
1761         }
1762
1763         if (validateFlash2xReadWrite(ad, &sFlash2xWrite) == false)
1764                 return STATUS_FAILURE;
1765
1766         input_addr = sFlash2xWrite.pDataBuff;
1767         write_off = sFlash2xWrite.offset;
1768         nob = sFlash2xWrite.numOfBytes;
1769
1770         if (nob > ad->uiSectorSize)
1771                 buff_size = ad->uiSectorSize;
1772         else
1773                 buff_size = nob;
1774
1775         write_buff = kmalloc(buff_size, GFP_KERNEL);
1776
1777         if (write_buff == NULL)
1778                 return -ENOMEM;
1779
1780         /* extracting the remainder of the given offset. */
1781         write_bytes = ad->uiSectorSize;
1782         if (write_off % ad->uiSectorSize) {
1783                 write_bytes = ad->uiSectorSize -
1784                         (write_off % ad->uiSectorSize);
1785         }
1786
1787         if (nob < write_bytes)
1788                 write_bytes = nob;
1789
1790         down(&ad->NVMRdmWrmLock);
1791
1792         if ((ad->IdleMode == TRUE) ||
1793                 (ad->bShutStatus == TRUE) ||
1794                 (ad->bPreparingForLowPowerMode == TRUE)) {
1795
1796                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1797                         "Device is in Idle/Shutdown Mode\n");
1798                 up(&ad->NVMRdmWrmLock);
1799                 kfree(write_buff);
1800                 return -EACCES;
1801         }
1802
1803         BcmFlash2xCorruptSig(ad, sFlash2xWrite.Section);
1804         do {
1805                 status = copy_from_user(write_buff, input_addr, write_bytes);
1806                 if (status) {
1807                         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1808                                 "Copy to user failed with status :%d", status);
1809                         up(&ad->NVMRdmWrmLock);
1810                         kfree(write_buff);
1811                         return -EFAULT;
1812                 }
1813                 BCM_DEBUG_PRINT_BUFFER(ad, DBG_TYPE_OTHERS,
1814                         OSAL_DBG, DBG_LVL_ALL, write_buff, write_bytes);
1815
1816                 /* Writing the data from Flash 2.x */
1817                 status = BcmFlash2xBulkWrite(ad, (PUINT)write_buff,
1818                                              sFlash2xWrite.Section,
1819                                              write_off,
1820                                              write_bytes,
1821                                              sFlash2xWrite.bVerify);
1822
1823                 if (status) {
1824                         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1825                                 "Flash 2x read err with status :%d", status);
1826                         break;
1827                 }
1828
1829                 nob = nob - write_bytes;
1830                 if (nob) {
1831                         write_off = write_off + write_bytes;
1832                         input_addr = input_addr + write_bytes;
1833                         if (nob > ad->uiSectorSize)
1834                                 write_bytes = ad->uiSectorSize;
1835                         else
1836                                 write_bytes = nob;
1837                 }
1838         } while (nob > 0);
1839
1840         BcmFlash2xWriteSig(ad, sFlash2xWrite.Section);
1841         up(&ad->NVMRdmWrmLock);
1842         kfree(write_buff);
1843         return status;
1844 }
1845
1846 static int bcm_char_ioctl_flash2x_section_bitmap(void __user *argp,
1847         struct bcm_mini_adapter *ad)
1848 {
1849         struct bcm_flash2x_bitmap *flash_2x_bit_map;
1850         struct bcm_ioctl_buffer io_buff;
1851
1852 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1853         "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called");
1854
1855         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
1856                 return -EFAULT;
1857
1858         if (io_buff.OutputLength != sizeof(struct bcm_flash2x_bitmap))
1859                 return -EINVAL;
1860
1861         flash_2x_bit_map = kzalloc(sizeof(struct bcm_flash2x_bitmap),
1862                         GFP_KERNEL);
1863
1864         if (flash_2x_bit_map == NULL) {
1865                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1866                         "Memory is not available");
1867                 return -ENOMEM;
1868         }
1869
1870         /* Reading the Flash Sectio Bit map */
1871         down(&ad->NVMRdmWrmLock);
1872
1873         if ((ad->IdleMode == TRUE) ||
1874                 (ad->bShutStatus == TRUE) ||
1875                 (ad->bPreparingForLowPowerMode == TRUE)) {
1876
1877                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1878                         "Device is in Idle/Shutdown Mode\n");
1879                 up(&ad->NVMRdmWrmLock);
1880                 kfree(flash_2x_bit_map);
1881                 return -EACCES;
1882         }
1883
1884         BcmGetFlash2xSectionalBitMap(ad, flash_2x_bit_map);
1885         up(&ad->NVMRdmWrmLock);
1886         if (copy_to_user(io_buff.OutputBuffer, flash_2x_bit_map,
1887                 sizeof(struct bcm_flash2x_bitmap))) {
1888                 kfree(flash_2x_bit_map);
1889                 return -EFAULT;
1890         }
1891
1892         kfree(flash_2x_bit_map);
1893         return STATUS_FAILURE;
1894 }
1895
1896 static int bcm_char_ioctl_set_active_section(void __user *argp,
1897                                              struct bcm_mini_adapter *ad)
1898 {
1899         enum bcm_flash2x_section_val flash_2x_section_val = 0;
1900         INT status = STATUS_FAILURE;
1901         struct bcm_ioctl_buffer io_buff;
1902
1903         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1904                         "IOCTL_BCM_SET_ACTIVE_SECTION Called");
1905
1906         if (IsFlash2x(ad) != TRUE) {
1907                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1908                                 "Flash Does not have 2.x map");
1909                 return -EINVAL;
1910         }
1911
1912         status = copy_from_user(&io_buff, argp,
1913                                 sizeof(struct bcm_ioctl_buffer));
1914         if (status) {
1915                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1916                                 "Copy of IOCTL BUFFER failed");
1917                 return -EFAULT;
1918         }
1919
1920         status = copy_from_user(&flash_2x_section_val,
1921                                 io_buff.InputBuffer, sizeof(INT));
1922         if (status) {
1923                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1924                         "Copy of flash section val failed");
1925                 return -EFAULT;
1926         }
1927
1928         down(&ad->NVMRdmWrmLock);
1929
1930         if ((ad->IdleMode == TRUE) ||
1931                 (ad->bShutStatus == TRUE) ||
1932                 (ad->bPreparingForLowPowerMode == TRUE)) {
1933
1934                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1935                                 "Device is in Idle/Shutdown Mode\n");
1936                 up(&ad->NVMRdmWrmLock);
1937                 return -EACCES;
1938         }
1939
1940         status = BcmSetActiveSection(ad, flash_2x_section_val);
1941         if (status)
1942                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1943                                 "Failed to make it's priority Highest. status %d",
1944                                 status);
1945
1946         up(&ad->NVMRdmWrmLock);
1947
1948         return status;
1949 }
1950
1951 static int bcm_char_ioctl_copy_section(void __user *argp,
1952                                        struct bcm_mini_adapter *ad)
1953 {
1954         struct bcm_flash2x_copy_section copy_sect_strut = {0};
1955         struct bcm_ioctl_buffer io_buff;
1956         INT status = STATUS_SUCCESS;
1957
1958         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1959                         "IOCTL_BCM_COPY_SECTION  Called");
1960
1961         ad->bAllDSDWriteAllow = false;
1962         if (IsFlash2x(ad) != TRUE) {
1963                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1964                                 "Flash Does not have 2.x map");
1965                 return -EINVAL;
1966         }
1967
1968         status = copy_from_user(&io_buff, argp,
1969                                 sizeof(struct bcm_ioctl_buffer));
1970         if (status) {
1971                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1972                                 "Copy of IOCTL BUFFER failed status :%d",
1973                                 status);
1974                 return -EFAULT;
1975         }
1976
1977         status = copy_from_user(&copy_sect_strut, io_buff.InputBuffer,
1978                                 sizeof(struct bcm_flash2x_copy_section));
1979         if (status) {
1980                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1981                                 "Copy of Copy_Section_Struct failed with status :%d",
1982                                 status);
1983                 return -EFAULT;
1984         }
1985
1986         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1987                         "Source SEction :%x", copy_sect_strut.SrcSection);
1988         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1989                         "Destination SEction :%x", copy_sect_strut.DstSection);
1990         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1991                         "offset :%x", copy_sect_strut.offset);
1992         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
1993                         "nob :%x", copy_sect_strut.numOfBytes);
1994
1995         if (IsSectionExistInFlash(ad, copy_sect_strut.SrcSection) == false) {
1996                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
1997                                 "Source Section<%x> does not exist in Flash ",
1998                                 copy_sect_strut.SrcSection);
1999                 return -EINVAL;
2000         }
2001
2002         if (IsSectionExistInFlash(ad, copy_sect_strut.DstSection) == false) {
2003                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2004                                 "Destinatio Section<%x> does not exist in Flash ",
2005                                 copy_sect_strut.DstSection);
2006                 return -EINVAL;
2007         }
2008
2009         if (copy_sect_strut.SrcSection == copy_sect_strut.DstSection) {
2010                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2011                                 "Source and Destination section should be different");
2012                 return -EINVAL;
2013         }
2014
2015         down(&ad->NVMRdmWrmLock);
2016
2017         if ((ad->IdleMode == TRUE) ||
2018                 (ad->bShutStatus == TRUE) ||
2019                 (ad->bPreparingForLowPowerMode == TRUE)) {
2020
2021                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2022                                 "Device is in Idle/Shutdown Mode\n");
2023                 up(&ad->NVMRdmWrmLock);
2024                 return -EACCES;
2025         }
2026
2027         if (copy_sect_strut.SrcSection == ISO_IMAGE1 ||
2028                 copy_sect_strut.SrcSection == ISO_IMAGE2) {
2029                 if (IsNonCDLessDevice(ad)) {
2030                         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2031                                         "Device is Non-CDLess hence won't have ISO !!");
2032                         status = -EINVAL;
2033                 } else if (copy_sect_strut.numOfBytes == 0) {
2034                         status = BcmCopyISO(ad, copy_sect_strut);
2035                 } else {
2036                         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2037                                         "Partial Copy of ISO section is not Allowed..");
2038                         status = STATUS_FAILURE;
2039                 }
2040                 up(&ad->NVMRdmWrmLock);
2041                 return status;
2042         }
2043
2044         status = BcmCopySection(ad, copy_sect_strut.SrcSection,
2045                                 copy_sect_strut.DstSection,
2046                                 copy_sect_strut.offset,
2047                                 copy_sect_strut.numOfBytes);
2048         up(&ad->NVMRdmWrmLock);
2049         return status;
2050 }
2051
2052 static int bcm_char_ioctl_get_flash_cs_info(void __user *argp,
2053                                             struct bcm_mini_adapter *ad)
2054 {
2055         struct bcm_ioctl_buffer io_buff;
2056         INT status = STATUS_SUCCESS;
2057
2058         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2059                         " IOCTL_BCM_GET_FLASH_CS_INFO Called");
2060
2061         status = copy_from_user(&io_buff, argp,
2062                         sizeof(struct bcm_ioctl_buffer));
2063         if (status) {
2064                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2065                                 "Copy of IOCTL BUFFER failed");
2066                 return -EFAULT;
2067         }
2068
2069         if (ad->eNVMType != NVM_FLASH) {
2070                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2071                                 "Connected device does not have flash");
2072                 return -EINVAL;
2073         }
2074
2075         if (IsFlash2x(ad) == TRUE) {
2076                 if (io_buff.OutputLength < sizeof(struct bcm_flash2x_cs_info))
2077                         return -EINVAL;
2078
2079                 if (copy_to_user(io_buff.OutputBuffer,
2080                                  ad->psFlash2xCSInfo,
2081                                  sizeof(struct bcm_flash2x_cs_info)))
2082                         return -EFAULT;
2083         } else {
2084                 if (io_buff.OutputLength < sizeof(struct bcm_flash_cs_info))
2085                         return -EINVAL;
2086
2087                 if (copy_to_user(io_buff.OutputBuffer, ad->psFlashCSInfo,
2088                                  sizeof(struct bcm_flash_cs_info)))
2089                         return -EFAULT;
2090         }
2091         return status;
2092 }
2093
2094 static int bcm_char_ioctl_select_dsd(void __user *argp,
2095                                      struct bcm_mini_adapter *ad)
2096 {
2097         struct bcm_ioctl_buffer io_buff;
2098         INT status = STATUS_FAILURE;
2099         UINT sect_offset = 0;
2100         enum bcm_flash2x_section_val flash_2x_section_val;
2101
2102         flash_2x_section_val = NO_SECTION_VAL;
2103         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2104                         "IOCTL_BCM_SELECT_DSD Called");
2105
2106         if (IsFlash2x(ad) != TRUE) {
2107                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2108                                 "Flash Does not have 2.x map");
2109                 return -EINVAL;
2110         }
2111
2112         status = copy_from_user(&io_buff, argp,
2113                                 sizeof(struct bcm_ioctl_buffer));
2114         if (status) {
2115                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2116                                 "Copy of IOCTL BUFFER failed");
2117                 return -EFAULT;
2118         }
2119         status = copy_from_user(&flash_2x_section_val, io_buff.InputBuffer,
2120                 sizeof(INT));
2121         if (status) {
2122                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2123                                 "Copy of flash section val failed");
2124                 return -EFAULT;
2125         }
2126
2127         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2128                         "Read Section :%d", flash_2x_section_val);
2129         if ((flash_2x_section_val != DSD0) &&
2130                 (flash_2x_section_val != DSD1) &&
2131                 (flash_2x_section_val != DSD2)) {
2132
2133                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2134                                 "Passed section<%x> is not DSD section",
2135                                 flash_2x_section_val);
2136                 return STATUS_FAILURE;
2137         }
2138
2139         sect_offset = BcmGetSectionValStartOffset(ad, flash_2x_section_val);
2140         if (sect_offset == INVALID_OFFSET) {
2141                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2142                                 "Provided Section val <%d> does not exist in Flash 2.x",
2143                                 flash_2x_section_val);
2144                 return -EINVAL;
2145         }
2146
2147         ad->bAllDSDWriteAllow = TRUE;
2148         ad->ulFlashCalStart = sect_offset;
2149         ad->eActiveDSD = flash_2x_section_val;
2150
2151         return STATUS_SUCCESS;
2152 }
2153
2154 static int bcm_char_ioctl_nvm_raw_read(void __user *argp,
2155                                        struct bcm_mini_adapter *ad)
2156 {
2157         struct bcm_nvm_readwrite nvm_read;
2158         struct bcm_ioctl_buffer io_buff;
2159         unsigned int nob;
2160         INT buff_size;
2161         INT read_offset = 0;
2162         UINT read_bytes = 0;
2163         PUCHAR read_buff;
2164         void __user *OutPutBuff;
2165         INT status = STATUS_FAILURE;
2166
2167         if (ad->eNVMType != NVM_FLASH) {
2168                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2169                                 "NVM TYPE is not Flash");
2170                 return -EINVAL;
2171         }
2172
2173         /* Copy Ioctl Buffer structure */
2174         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer))) {
2175                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2176                                 "copy_from_user 1 failed\n");
2177                 return -EFAULT;
2178         }
2179
2180         if (copy_from_user(&nvm_read, io_buff.OutputBuffer,
2181                 sizeof(struct bcm_nvm_readwrite)))
2182                 return -EFAULT;
2183
2184         nob = nvm_read.uiNumBytes;
2185         /* In Raw-Read max Buff size : 64MB */
2186
2187         if (nob > DEFAULT_BUFF_SIZE)
2188                 buff_size = DEFAULT_BUFF_SIZE;
2189         else
2190                 buff_size = nob;
2191
2192         read_offset = nvm_read.uiOffset;
2193         OutPutBuff = nvm_read.pBuffer;
2194
2195         read_buff = kzalloc(buff_size , GFP_KERNEL);
2196         if (read_buff == NULL) {
2197                 BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2198                                 "Memory allocation failed for Flash 2.x Read Structure");
2199                 return -ENOMEM;
2200         }
2201         down(&ad->NVMRdmWrmLock);
2202
2203         if ((ad->IdleMode == TRUE) ||
2204                 (ad->bShutStatus == TRUE) ||
2205                 (ad->bPreparingForLowPowerMode == TRUE)) {
2206
2207                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2208                                 "Device is in Idle/Shutdown Mode\n");
2209                 kfree(read_buff);
2210                 up(&ad->NVMRdmWrmLock);
2211                 return -EACCES;
2212         }
2213
2214         ad->bFlashRawRead = TRUE;
2215
2216         while (nob) {
2217                 if (nob > DEFAULT_BUFF_SIZE)
2218                         read_bytes = DEFAULT_BUFF_SIZE;
2219                 else
2220                         read_bytes = nob;
2221
2222                 /* Reading the data from Flash 2.x */
2223                 status = BeceemNVMRead(ad, (PUINT)read_buff,
2224                         read_offset, read_bytes);
2225                 if (status) {
2226                         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2227                                         "Flash 2x read err with status :%d",
2228                                         status);
2229                         break;
2230                 }
2231
2232                 BCM_DEBUG_PRINT_BUFFER(ad, DBG_TYPE_OTHERS, OSAL_DBG,
2233                                        DBG_LVL_ALL, read_buff, read_bytes);
2234
2235                 status = copy_to_user(OutPutBuff, read_buff, read_bytes);
2236                 if (status) {
2237                         BCM_DEBUG_PRINT(ad, DBG_TYPE_PRINTK, 0, 0,
2238                                         "Copy to use failed with status :%d",
2239                                         status);
2240                         up(&ad->NVMRdmWrmLock);
2241                         kfree(read_buff);
2242                         return -EFAULT;
2243                 }
2244                 nob = nob - read_bytes;
2245                 if (nob) {
2246                         read_offset = read_offset + read_bytes;
2247                         OutPutBuff = OutPutBuff + read_bytes;
2248                 }
2249         }
2250         ad->bFlashRawRead = false;
2251         up(&ad->NVMRdmWrmLock);
2252         kfree(read_buff);
2253         return status;
2254 }
2255
2256 static int bcm_char_ioctl_cntrlmsg_mask(void __user *argp,
2257                                         struct bcm_mini_adapter *ad,
2258                                         struct bcm_tarang_data *tarang)
2259 {
2260         struct bcm_ioctl_buffer io_buff;
2261         INT status = STATUS_FAILURE;
2262         ULONG rx_cntrl_msg_bit_mask = 0;
2263
2264         /* Copy Ioctl Buffer structure */
2265         status = copy_from_user(&io_buff, argp,
2266                         sizeof(struct bcm_ioctl_buffer));
2267         if (status) {
2268                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2269                                 "copy of Ioctl buffer is failed from user space");
2270                 return -EFAULT;
2271         }
2272
2273         if (io_buff.InputLength != sizeof(unsigned long))
2274                 return -EINVAL;
2275
2276         status = copy_from_user(&rx_cntrl_msg_bit_mask, io_buff.InputBuffer,
2277                                 io_buff.InputLength);
2278         if (status) {
2279                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2280                                 "copy of control bit mask failed from user space");
2281                 return -EFAULT;
2282         }
2283         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2284                         "\n Got user defined cntrl msg bit mask :%lx",
2285                         rx_cntrl_msg_bit_mask);
2286         tarang->RxCntrlMsgBitMask = rx_cntrl_msg_bit_mask;
2287
2288         return status;
2289 }
2290
2291 static int bcm_char_ioctl_get_device_driver_info(void __user *argp,
2292         struct bcm_mini_adapter *ad)
2293 {
2294         struct bcm_driver_info dev_info;
2295         struct bcm_ioctl_buffer io_buff;
2296
2297         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2298                         "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n");
2299
2300         memset(&dev_info, 0, sizeof(dev_info));
2301         dev_info.MaxRDMBufferSize = BUFFER_4K;
2302         dev_info.u32DSDStartOffset = EEPROM_CALPARAM_START;
2303         dev_info.u32RxAlignmentCorrection = 0;
2304         dev_info.u32NVMType = ad->eNVMType;
2305         dev_info.u32InterfaceType = BCM_USB;
2306
2307         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
2308                 return -EFAULT;
2309
2310         if (io_buff.OutputLength < sizeof(dev_info))
2311                 return -EINVAL;
2312
2313         if (copy_to_user(io_buff.OutputBuffer, &dev_info, sizeof(dev_info)))
2314                 return -EFAULT;
2315
2316         return STATUS_SUCCESS;
2317 }
2318
2319 static int bcm_char_ioctl_time_since_net_entry(void __user *argp,
2320         struct bcm_mini_adapter *ad)
2321 {
2322         struct bcm_time_elapsed time_elapsed_since_net_entry = {0};
2323         struct bcm_ioctl_buffer io_buff;
2324
2325         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2326                         "IOCTL_BCM_TIME_SINCE_NET_ENTRY called");
2327
2328         if (copy_from_user(&io_buff, argp, sizeof(struct bcm_ioctl_buffer)))
2329                 return -EFAULT;
2330
2331         if (io_buff.OutputLength < sizeof(struct bcm_time_elapsed))
2332                 return -EINVAL;
2333
2334         time_elapsed_since_net_entry.ul64TimeElapsedSinceNetEntry =
2335                 get_seconds() - ad->liTimeSinceLastNetEntry;
2336
2337         if (copy_to_user(io_buff.OutputBuffer, &time_elapsed_since_net_entry,
2338                          sizeof(struct bcm_time_elapsed)))
2339                 return -EFAULT;
2340
2341         return STATUS_SUCCESS;
2342 }
2343
2344
2345 static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
2346 {
2347         struct bcm_tarang_data *tarang = filp->private_data;
2348         void __user *argp = (void __user *)arg;
2349         struct bcm_mini_adapter *ad = tarang->Adapter;
2350         INT status = STATUS_FAILURE;
2351
2352         BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2353                         "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX",
2354                         cmd, arg);
2355
2356         if (_IOC_TYPE(cmd) != BCM_IOCTL)
2357                 return -EFAULT;
2358         if (_IOC_DIR(cmd) & _IOC_READ)
2359                 status = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd));
2360         else if (_IOC_DIR(cmd) & _IOC_WRITE)
2361                 status = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd));
2362         else if (_IOC_NONE == (_IOC_DIR(cmd) & _IOC_NONE))
2363                 status = STATUS_SUCCESS;
2364
2365         if (status)
2366                 return -EFAULT;
2367
2368         if (ad->device_removed)
2369                 return -EFAULT;
2370
2371         if (false == ad->fw_download_done) {
2372                 switch (cmd) {
2373                 case IOCTL_MAC_ADDR_REQ:
2374                 case IOCTL_LINK_REQ:
2375                 case IOCTL_CM_REQUEST:
2376                 case IOCTL_SS_INFO_REQ:
2377                 case IOCTL_SEND_CONTROL_MESSAGE:
2378                 case IOCTL_IDLE_REQ:
2379                 case IOCTL_BCM_GPIO_SET_REQUEST:
2380                 case IOCTL_BCM_GPIO_STATUS_REQUEST:
2381                         return -EACCES;
2382                 default:
2383                         break;
2384                 }
2385         }
2386
2387         status = vendorextnIoctl(ad, cmd, arg);
2388         if (status != CONTINUE_COMMON_PATH)
2389                 return status;
2390
2391         switch (cmd) {
2392         /* Rdms for Swin Idle... */
2393         case IOCTL_BCM_REGISTER_READ_PRIVATE:
2394                 status = bcm_char_ioctl_reg_read_private(argp, ad);
2395                 return status;
2396
2397         case IOCTL_BCM_REGISTER_WRITE_PRIVATE:
2398                 status = bcm_char_ioctl_reg_write_private(argp, ad);
2399                 return status;
2400
2401         case IOCTL_BCM_REGISTER_READ:
2402         case IOCTL_BCM_EEPROM_REGISTER_READ:
2403                 status = bcm_char_ioctl_eeprom_reg_read(argp, ad);
2404                 return status;
2405
2406         case IOCTL_BCM_REGISTER_WRITE:
2407         case IOCTL_BCM_EEPROM_REGISTER_WRITE:
2408                 status = bcm_char_ioctl_eeprom_reg_write(argp, ad, cmd);
2409                 return status;
2410
2411         case IOCTL_BCM_GPIO_SET_REQUEST:
2412                 status = bcm_char_ioctl_gpio_set_request(argp, ad);
2413                 return status;
2414
2415         case BCM_LED_THREAD_STATE_CHANGE_REQ:
2416                 status = bcm_char_ioctl_led_thread_state_change_req(argp,
2417                                                                     ad);
2418                 return status;
2419
2420         case IOCTL_BCM_GPIO_STATUS_REQUEST:
2421                 status = bcm_char_ioctl_gpio_status_request(argp, ad);
2422                 return status;
2423
2424         case IOCTL_BCM_GPIO_MULTI_REQUEST:
2425                 status = bcm_char_ioctl_gpio_multi_request(argp, ad);
2426                 return status;
2427
2428         case IOCTL_BCM_GPIO_MODE_REQUEST:
2429                 status = bcm_char_ioctl_gpio_mode_request(argp, ad);
2430                 return status;
2431
2432         case IOCTL_MAC_ADDR_REQ:
2433         case IOCTL_LINK_REQ:
2434         case IOCTL_CM_REQUEST:
2435         case IOCTL_SS_INFO_REQ:
2436         case IOCTL_SEND_CONTROL_MESSAGE:
2437         case IOCTL_IDLE_REQ:
2438                 status = bcm_char_ioctl_misc_request(argp, ad);
2439                 return status;
2440
2441         case IOCTL_BCM_BUFFER_DOWNLOAD_START:
2442                 status = bcm_char_ioctl_buffer_download_start(ad);
2443                 return status;
2444
2445         case IOCTL_BCM_BUFFER_DOWNLOAD:
2446                 status = bcm_char_ioctl_buffer_download(argp, ad);
2447                 return status;
2448
2449         case IOCTL_BCM_BUFFER_DOWNLOAD_STOP:
2450                 status = bcm_char_ioctl_buffer_download_stop(argp, ad);
2451                 return status;
2452
2453
2454         case IOCTL_BE_BUCKET_SIZE:
2455                 status = 0;
2456                 if (get_user(ad->BEBucketSize,
2457                              (unsigned long __user *)arg))
2458                         status = -EFAULT;
2459                 break;
2460
2461         case IOCTL_RTPS_BUCKET_SIZE:
2462                 status = 0;
2463                 if (get_user(ad->rtPSBucketSize,
2464                              (unsigned long __user *)arg))
2465                         status = -EFAULT;
2466                 break;
2467
2468         case IOCTL_CHIP_RESET:
2469                 status = bcm_char_ioctl_chip_reset(ad);
2470                 return status;
2471
2472         case IOCTL_QOS_THRESHOLD:
2473                 status = bcm_char_ioctl_qos_threshold(arg, ad);
2474                 return status;
2475
2476         case IOCTL_DUMP_PACKET_INFO:
2477                 DumpPackInfo(ad);
2478                 DumpPhsRules(&ad->stBCMPhsContext);
2479                 status = STATUS_SUCCESS;
2480                 break;
2481
2482         case IOCTL_GET_PACK_INFO:
2483                 if (copy_to_user(argp, &ad->PackInfo,
2484                                  sizeof(struct bcm_packet_info)*NO_OF_QUEUES))
2485                         return -EFAULT;
2486                 status = STATUS_SUCCESS;
2487                 break;
2488
2489         case IOCTL_BCM_SWITCH_TRANSFER_MODE:
2490                 status = bcm_char_ioctl_switch_transfer_mode(argp, ad);
2491                 return status;
2492
2493         case IOCTL_BCM_GET_DRIVER_VERSION:
2494                 status = bcm_char_ioctl_get_driver_version(argp);
2495                 return status;
2496
2497         case IOCTL_BCM_GET_CURRENT_STATUS:
2498                 status = bcm_char_ioctl_get_current_status(argp, ad);
2499                 return status;
2500
2501         case IOCTL_BCM_SET_MAC_TRACING:
2502                 status = bcm_char_ioctl_set_mac_tracing(argp, ad);
2503                 return status;
2504
2505         case IOCTL_BCM_GET_DSX_INDICATION:
2506                 status = bcm_char_ioctl_get_dsx_indication(argp, ad);
2507                 return status;
2508
2509         case IOCTL_BCM_GET_HOST_MIBS:
2510                 status = bcm_char_ioctl_get_host_mibs(argp, ad, tarang);
2511                 return status;
2512
2513         case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE:
2514                 if ((false == ad->bTriedToWakeUpFromlowPowerMode) &&
2515                                 (TRUE == ad->IdleMode)) {
2516                         ad->usIdleModePattern = ABORT_IDLE_MODE;
2517                         ad->bWakeUpDevice = TRUE;
2518                         wake_up(&ad->process_rx_cntrlpkt);
2519                 }
2520
2521                 status = STATUS_SUCCESS;
2522                 break;
2523
2524         case IOCTL_BCM_BULK_WRM:
2525                 status = bcm_char_ioctl_bulk_wrm(argp, ad, cmd);
2526                 return status;
2527
2528         case IOCTL_BCM_GET_NVM_SIZE:
2529                 status = bcm_char_ioctl_get_nvm_size(argp, ad);
2530                 return status;
2531
2532         case IOCTL_BCM_CAL_INIT:
2533                 status = bcm_char_ioctl_cal_init(argp, ad);
2534                 return status;
2535
2536         case IOCTL_BCM_SET_DEBUG:
2537                 status = bcm_char_ioctl_set_debug(argp, ad);
2538                 return status;
2539
2540         case IOCTL_BCM_NVM_READ:
2541         case IOCTL_BCM_NVM_WRITE:
2542                 status = bcm_char_ioctl_nvm_rw(argp, ad, cmd);
2543                 return status;
2544
2545         case IOCTL_BCM_FLASH2X_SECTION_READ:
2546                 status = bcm_char_ioctl_flash2x_section_read(argp, ad);
2547                 return status;
2548
2549         case IOCTL_BCM_FLASH2X_SECTION_WRITE:
2550                 status = bcm_char_ioctl_flash2x_section_write(argp, ad);
2551                 return status;
2552
2553         case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP:
2554                 status = bcm_char_ioctl_flash2x_section_bitmap(argp, ad);
2555                 return status;
2556
2557         case IOCTL_BCM_SET_ACTIVE_SECTION:
2558                 status = bcm_char_ioctl_set_active_section(argp, ad);
2559                 return status;
2560
2561         case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION:
2562                 /* Right Now we are taking care of only DSD */
2563                 ad->bAllDSDWriteAllow = false;
2564                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2565                                 "IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called");
2566                 status = STATUS_SUCCESS;
2567                 break;
2568
2569         case IOCTL_BCM_COPY_SECTION:
2570                 status = bcm_char_ioctl_copy_section(argp, ad);
2571                 return status;
2572
2573         case IOCTL_BCM_GET_FLASH_CS_INFO:
2574                 status = bcm_char_ioctl_get_flash_cs_info(argp, ad);
2575                 return status;
2576
2577         case IOCTL_BCM_SELECT_DSD:
2578                 status = bcm_char_ioctl_select_dsd(argp, ad);
2579                 return status;
2580
2581         case IOCTL_BCM_NVM_RAW_READ:
2582                 status = bcm_char_ioctl_nvm_raw_read(argp, ad);
2583                 return status;
2584
2585         case IOCTL_BCM_CNTRLMSG_MASK:
2586                 status = bcm_char_ioctl_cntrlmsg_mask(argp, ad, tarang);
2587                 return status;
2588
2589         case IOCTL_BCM_GET_DEVICE_DRIVER_INFO:
2590                 status = bcm_char_ioctl_get_device_driver_info(argp, ad);
2591                 return status;
2592
2593         case IOCTL_BCM_TIME_SINCE_NET_ENTRY:
2594                 status = bcm_char_ioctl_time_since_net_entry(argp, ad);
2595                 return status;
2596
2597         case IOCTL_CLOSE_NOTIFICATION:
2598                 BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
2599                                 "IOCTL_CLOSE_NOTIFICATION");
2600                 break;
2601
2602         default:
2603                 pr_info(DRV_NAME ": unknown ioctl cmd=%#x\n", cmd);
2604                 status = STATUS_FAILURE;
2605                 break;
2606         }
2607         return status;
2608 }
2609
2610
2611 static const struct file_operations bcm_fops = {
2612         .owner    = THIS_MODULE,
2613         .open     = bcm_char_open,
2614         .release  = bcm_char_release,
2615         .read     = bcm_char_read,
2616         .unlocked_ioctl    = bcm_char_ioctl,
2617         .llseek = no_llseek,
2618 };
2619
2620 int register_control_device_interface(struct bcm_mini_adapter *ad)
2621 {
2622
2623         if (ad->major > 0)
2624                 return ad->major;
2625
2626         ad->major = register_chrdev(0, DEV_NAME, &bcm_fops);
2627         if (ad->major < 0) {
2628                 pr_err(DRV_NAME ": could not created character device\n");
2629                 return ad->major;
2630         }
2631
2632         ad->pstCreatedClassDevice = device_create(bcm_class, NULL,
2633                                                        MKDEV(ad->major, 0),
2634                                                        ad, DEV_NAME);
2635
2636         if (IS_ERR(ad->pstCreatedClassDevice)) {
2637                 pr_err(DRV_NAME ": class device create failed\n");
2638                 unregister_chrdev(ad->major, DEV_NAME);
2639                 return PTR_ERR(ad->pstCreatedClassDevice);
2640         }
2641
2642         return 0;
2643 }
2644
2645 void unregister_control_device_interface(struct bcm_mini_adapter *ad)
2646 {
2647         if (ad->major > 0) {
2648                 device_destroy(bcm_class, MKDEV(ad->major, 0));
2649                 unregister_chrdev(ad->major, DEV_NAME);
2650         }
2651 }
2652