xref: /OK3568_Linux_fs/kernel/drivers/net/usb/GobiNet/QMIDevice.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*===========================================================================
2 FILE:
3    QMIDevice.c
4 
5 DESCRIPTION:
6    Functions related to the QMI interface device
7 
8 FUNCTIONS:
9    Generic functions
10       IsDeviceValid
11       PrintHex
12       GobiSetDownReason
13       GobiClearDownReason
14       GobiTestDownReason
15 
16    Driver level asynchronous read functions
17       ResubmitIntURB
18       ReadCallback
19       IntCallback
20       StartRead
21       KillRead
22 
23    Internal read/write functions
24       ReadAsync
25       UpSem
26       ReadSync
27       WriteSyncCallback
28       WriteSync
29 
30    Internal memory management functions
31       GetClientID
32       ReleaseClientID
33       FindClientMem
34       AddToReadMemList
35       PopFromReadMemList
36       AddToNotifyList
37       NotifyAndPopNotifyList
38       AddToURBList
39       PopFromURBList
40 
41    Internal userspace wrapper functions
42       UserspaceunlockedIOCTL
43 
44    Userspace wrappers
45       UserspaceOpen
46       UserspaceIOCTL
47       UserspaceClose
48       UserspaceRead
49       UserspaceWrite
50       UserspacePoll
51 
52    Initializer and destructor
53       RegisterQMIDevice
54       DeregisterQMIDevice
55 
56    Driver level client management
57       QMIReady
58       QMIWDSCallback
59       SetupQMIWDSCallback
60       QMIDMSGetMEID
61 
62 Copyright (c) 2011, Code Aurora Forum. All rights reserved.
63 
64 Redistribution and use in source and binary forms, with or without
65 modification, are permitted provided that the following conditions are met:
66     * Redistributions of source code must retain the above copyright
67       notice, this list of conditions and the following disclaimer.
68     * Redistributions in binary form must reproduce the above copyright
69       notice, this list of conditions and the following disclaimer in the
70       documentation and/or other materials provided with the distribution.
71     * Neither the name of Code Aurora Forum nor
72       the names of its contributors may be used to endorse or promote
73       products derived from this software without specific prior written
74       permission.
75 
76 
77 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
78 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
79 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
80 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
81 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
82 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
83 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
84 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
85 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
86 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
87 POSSIBILITY OF SUCH DAMAGE.
88 ===========================================================================*/
89 
90 //---------------------------------------------------------------------------
91 // Include Files
92 //---------------------------------------------------------------------------
93 #include <asm/unaligned.h>
94 #include <linux/module.h>
95 #include <linux/usb/cdc.h>
96 #include <linux/usb.h>
97 
98 //-----------------------------------------------------------------------------
99 // Definitions
100 //-----------------------------------------------------------------------------
101 
102 #define __QUEC_INCLUDE_QMI_C__
103 #include "QMI.c"
104 #define __QUECTEL_INTER__
105 #include "QMIDevice.h"
106 
107 #if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,22 ))
108 static int s_interval;
109 #endif
110 
111 #if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,14 ))
112 #include <linux/devfs_fs_kernel.h>
113 static char devfs_name[32];
device_create(struct class * class,struct device * parent,dev_t devt,const char * fmt,...)114 static int device_create(struct class *class,  struct device *parent, dev_t devt, const char *fmt, ...)
115 {
116    va_list vargs;
117    struct class_device *class_dev;
118    int err;
119 
120    va_start(vargs, fmt);
121    vsnprintf(devfs_name, sizeof(devfs_name), fmt, vargs);
122    va_end(vargs);
123 
124    class_dev = class_device_create(class, devt, parent, "%s", devfs_name);
125    if (IS_ERR(class_dev)) {
126       err = PTR_ERR(class_dev);
127       goto out;
128    }
129 
130    err = devfs_mk_cdev(devt, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, devfs_name);
131    if (err) {
132       class_device_destroy(class, devt);
133       goto out;
134    }
135 
136    return 0;
137 
138 out:
139    return err;
140 }
141 
device_destroy(struct class * class,dev_t devt)142 static void device_destroy(struct class *class, dev_t devt)
143 {
144    class_device_destroy(class, devt);
145    devfs_remove(devfs_name);
146 }
147 #endif
148 
149 #ifdef CONFIG_PM
150 // Prototype to GobiNetSuspend function
151 int QuecGobiNetSuspend(
152    struct usb_interface *     pIntf,
153    pm_message_t               powerEvent );
154 #endif /* CONFIG_PM */
155 
156 // IOCTL to generate a client ID for this service type
157 #define IOCTL_QMI_GET_SERVICE_FILE 0x8BE0 + 1
158 
159 // IOCTL to get the VIDPID of the device
160 #define IOCTL_QMI_GET_DEVICE_VIDPID 0x8BE0 + 2
161 
162 // IOCTL to get the MEID of the device
163 #define IOCTL_QMI_GET_DEVICE_MEID 0x8BE0 + 3
164 
165 #define IOCTL_QMI_RELEASE_SERVICE_FILE_IOCTL  (0x8BE0 + 4)
166 
167 // CDC GET_ENCAPSULATED_RESPONSE packet
168 #define CDC_GET_ENCAPSULATED_RESPONSE_LE 0x01A1ll
169 #define CDC_GET_ENCAPSULATED_RESPONSE_BE 0xA101000000000000ll
170 /* The following masks filter the common part of the encapsulated response
171  * packet value for Gobi and QMI devices, ie. ignore usb interface number
172  */
173 #define CDC_RSP_MASK_BE 0xFFFFFFFF00FFFFFFll
174 #define CDC_RSP_MASK_LE 0xFFFFFFE0FFFFFFFFll
175 
176 static const int i = 1;
177 #define is_bigendian() ( (*(char*)&i) == 0 )
178 #define CDC_GET_ENCAPSULATED_RESPONSE(pcdcrsp, pmask)\
179 {\
180    *pcdcrsp  = is_bigendian() ? CDC_GET_ENCAPSULATED_RESPONSE_BE \
181                           : CDC_GET_ENCAPSULATED_RESPONSE_LE ; \
182    *pmask = is_bigendian() ? CDC_RSP_MASK_BE \
183                            : CDC_RSP_MASK_LE; \
184 }
185 
186 // CDC CONNECTION_SPEED_CHANGE indication packet
187 #define CDC_CONNECTION_SPEED_CHANGE_LE 0x2AA1ll
188 #define CDC_CONNECTION_SPEED_CHANGE_BE 0xA12A000000000000ll
189 /* The following masks filter the common part of the connection speed change
190  * packet value for Gobi and QMI devices
191  */
192 #define CDC_CONNSPD_MASK_BE 0xFFFFFFFFFFFF7FFFll
193 #define CDC_CONNSPD_MASK_LE 0XFFF7FFFFFFFFFFFFll
194 #define CDC_GET_CONNECTION_SPEED_CHANGE(pcdccscp, pmask)\
195 {\
196    *pcdccscp  = is_bigendian() ? CDC_CONNECTION_SPEED_CHANGE_BE \
197                           : CDC_CONNECTION_SPEED_CHANGE_LE ; \
198    *pmask = is_bigendian() ? CDC_CONNSPD_MASK_BE \
199                            : CDC_CONNSPD_MASK_LE; \
200 }
201 
202 #define SET_CONTROL_LINE_STATE_REQUEST_TYPE        0x21
203 #define SET_CONTROL_LINE_STATE_REQUEST             0x22
204 #define CONTROL_DTR                     0x01
205 #define CONTROL_RTS                     0x02
206 
207 /*=========================================================================*/
208 // UserspaceQMIFops
209 //    QMI device's userspace file operations
210 /*=========================================================================*/
211 static struct file_operations UserspaceQMIFops =
212 {
213    .owner     = THIS_MODULE,
214    .read      = UserspaceRead,
215    .write     = UserspaceWrite,
216 #ifdef CONFIG_COMPAT
217    .compat_ioctl = UserspaceunlockedIOCTL,
218 #endif
219 #if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,36 ))
220    .unlocked_ioctl = UserspaceunlockedIOCTL,
221 #else
222    .ioctl     = UserspaceIOCTL,
223 #endif
224    .open      = UserspaceOpen,
225 #ifdef quectel_no_for_each_process
226    .release      = UserspaceClose,
227 #else
228    .flush     = UserspaceClose,
229 #endif
230    .poll      = UserspacePoll,
231 };
232 
233 /*=========================================================================*/
234 // Generic functions
235 /*=========================================================================*/
QMIXactionIDGet(sGobiUSBNet * pDev)236 static u8 QMIXactionIDGet( sGobiUSBNet *pDev)
237 {
238    u8 transactionID;
239 
240    if( 0 == (transactionID = atomic_add_return( 1, &pDev->mQMIDev.mQMICTLTransactionID)) )
241    {
242       transactionID = atomic_add_return( 1, &pDev->mQMIDev.mQMICTLTransactionID );
243    }
244 
245 #if 1 //free these ununsed qmi response, or when these transactionID re-used, they will be regarded as qmi response of the qmi request that have same transactionID
246     if (transactionID) {
247         unsigned long flags;
248         void * pReadBuffer;
249         u16 readBufferSize;
250 
251          spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
252          while (PopFromReadMemList( pDev,
253                                  QMICTL,
254                                  transactionID,
255                                  &pReadBuffer,
256                                  &readBufferSize ) == true)
257         {
258             kfree( pReadBuffer );
259         }
260         spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
261     }
262 #endif
263 
264    return transactionID;
265 }
266 
GetEndpoint(struct usb_interface * pintf,int type,int dir)267 static struct usb_endpoint_descriptor *GetEndpoint(
268     struct usb_interface *pintf,
269     int type,
270     int dir )
271 {
272    int i;
273    struct usb_host_interface *iface = pintf->cur_altsetting;
274    struct usb_endpoint_descriptor *pendp;
275 
276    for( i = 0; i < iface->desc.bNumEndpoints; i++)
277    {
278       pendp = &iface->endpoint[i].desc;
279       if( ((pendp->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == dir)
280           &&
281           (usb_endpoint_type(pendp) == type) )
282       {
283          return pendp;
284       }
285    }
286 
287    return NULL;
288 }
289 
290 /*===========================================================================
291 METHOD:
292    IsDeviceValid (Public Method)
293 
294 DESCRIPTION:
295    Basic test to see if device memory is valid
296 
297 PARAMETERS:
298    pDev     [ I ] - Device specific memory
299 
300 RETURN VALUE:
301    bool
302 ===========================================================================*/
IsDeviceValid(sGobiUSBNet * pDev)303 static bool IsDeviceValid( sGobiUSBNet * pDev )
304 {
305    if (pDev == NULL)
306    {
307       return false;
308    }
309 
310    if (pDev->mbQMIValid == false)
311    {
312       return false;
313    }
314 
315    return true;
316 }
317 
318 /*===========================================================================
319 METHOD:
320    PrintHex (Public Method)
321 
322 DESCRIPTION:
323    Print Hex data, for debug purposes
324 
325 PARAMETERS:
326    pBuffer       [ I ] - Data buffer
327    bufSize       [ I ] - Size of data buffer
328 
329 RETURN VALUE:
330    None
331 ===========================================================================*/
QuecPrintHex(void * pBuffer,u16 bufSize)332 void QuecPrintHex(
333    void *      pBuffer,
334    u16         bufSize )
335 {
336    char * pPrintBuf;
337    u16 pos;
338    int status;
339 
340    if (quec_debug != 1)
341    {
342        return;
343    }
344 
345    pPrintBuf = kmalloc( bufSize * 3 + 1, GFP_ATOMIC );
346    if (pPrintBuf == NULL)
347    {
348       DBG( "Unable to allocate buffer\n" );
349       return;
350    }
351    memset( pPrintBuf, 0 , bufSize * 3 + 1 );
352 
353    for (pos = 0; pos < bufSize; pos++)
354    {
355       status = snprintf( (pPrintBuf + (pos * 3)),
356                          4,
357                          "%02X ",
358                          *(u8 *)(pBuffer + pos) );
359       if (status != 3)
360       {
361          DBG( "snprintf error %d\n", status );
362          kfree( pPrintBuf );
363          return;
364       }
365    }
366 
367    DBG( "   : %s\n", pPrintBuf );
368 
369    kfree( pPrintBuf );
370    pPrintBuf = NULL;
371    return;
372 }
373 
374 /*===========================================================================
375 METHOD:
376    GobiSetDownReason (Public Method)
377 
378 DESCRIPTION:
379    Sets mDownReason and turns carrier off
380 
381 PARAMETERS
382    pDev     [ I ] - Device specific memory
383    reason   [ I ] - Reason device is down
384 
385 RETURN VALUE:
386    None
387 ===========================================================================*/
QuecGobiSetDownReason(sGobiUSBNet * pDev,u8 reason)388 void QuecGobiSetDownReason(
389    sGobiUSBNet *    pDev,
390    u8                 reason )
391 {
392    DBG("%s reason=%d, mDownReason=%x\n", __func__, reason, (unsigned)pDev->mDownReason);
393 
394 #ifdef QUECTEL_WWAN_QMAP
395    if (reason == NO_NDIS_CONNECTION)
396       return;
397 #endif
398 
399    set_bit( reason, &pDev->mDownReason );
400 
401    netif_carrier_off( pDev->mpNetDev->net );
402 }
403 
404 /*===========================================================================
405 METHOD:
406    GobiClearDownReason (Public Method)
407 
408 DESCRIPTION:
409    Clear mDownReason and may turn carrier on
410 
411 PARAMETERS
412    pDev     [ I ] - Device specific memory
413    reason   [ I ] - Reason device is no longer down
414 
415 RETURN VALUE:
416    None
417 ===========================================================================*/
QuecGobiClearDownReason(sGobiUSBNet * pDev,u8 reason)418 void QuecGobiClearDownReason(
419    sGobiUSBNet *    pDev,
420    u8                 reason )
421 {
422    clear_bit( reason, &pDev->mDownReason );
423 
424    DBG("%s reason=%d, mDownReason=%x\n", __func__, reason, (unsigned)pDev->mDownReason);
425 #if 0 //(LINUX_VERSION_CODE >= KERNEL_VERSION( 3,11,0 ))
426     netif_carrier_on( pDev->mpNetDev->net );
427 #else
428    if (pDev->mDownReason == 0)
429    {
430 #ifdef QUECTEL_WWAN_QMAP
431       if (pDev->qmap_mode && !pDev->link_state)
432          ;
433       else
434 #endif
435       netif_carrier_on( pDev->mpNetDev->net );
436    }
437 #endif
438 }
439 
440 /*===========================================================================
441 METHOD:
442    GobiTestDownReason (Public Method)
443 
444 DESCRIPTION:
445    Test mDownReason and returns whether reason is set
446 
447 PARAMETERS
448    pDev     [ I ] - Device specific memory
449    reason   [ I ] - Reason device is down
450 
451 RETURN VALUE:
452    bool
453 ===========================================================================*/
QuecGobiTestDownReason(sGobiUSBNet * pDev,u8 reason)454 bool QuecGobiTestDownReason(
455    sGobiUSBNet *    pDev,
456    u8                 reason )
457 {
458    return test_bit( reason, &pDev->mDownReason );
459 }
460 
461 /*=========================================================================*/
462 // Driver level asynchronous read functions
463 /*=========================================================================*/
464 
465 /*===========================================================================
466 METHOD:
467    ResubmitIntURB (Public Method)
468 
469 DESCRIPTION:
470    Resubmit interrupt URB, re-using same values
471 
472 PARAMETERS
473    pIntURB       [ I ] - Interrupt URB
474 
475 RETURN VALUE:
476    int - 0 for success
477          negative errno for failure
478 ===========================================================================*/
ResubmitIntURB(struct urb * pIntURB)479 static int ResubmitIntURB( struct urb * pIntURB )
480 {
481    int status;
482    int interval;
483 
484    // Sanity test
485    if ( (pIntURB == NULL)
486    ||   (pIntURB->dev == NULL) )
487    {
488       return -EINVAL;
489    }
490 
491    // Interval needs reset after every URB completion
492 #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,22 ))
493     interval = max((int)(pIntURB->ep->desc.bInterval),
494                   (pIntURB->dev->speed == USB_SPEED_HIGH) ? 7 : 3);
495 #else
496     interval = s_interval;
497 #endif
498 
499    // Reschedule interrupt URB
500    usb_fill_int_urb( pIntURB,
501                      pIntURB->dev,
502                      pIntURB->pipe,
503                      pIntURB->transfer_buffer,
504                      pIntURB->transfer_buffer_length,
505                      pIntURB->complete,
506                      pIntURB->context,
507                      interval );
508    status = usb_submit_urb( pIntURB, GFP_ATOMIC );
509    if (status != 0)
510    {
511       DBG( "Error re-submitting Int URB %d\n", status );
512    }
513 
514    return status;
515 }
516 
517 
518 #ifdef QUECTEL_QMI_MERGE
MergeRecQmiMsg(sQMIDev * pQMIDev,struct urb * pReadURB)519 static int MergeRecQmiMsg( sQMIDev * pQMIDev, struct urb * pReadURB )
520 {
521    sQMIMsgHeader * mHeader;
522    sQMIMsgPacket * mPacket;
523 
524    DBG( "%s called \n", __func__ );
525    mPacket = pQMIDev->mpQmiMsgPacket;
526 
527    if(pReadURB->actual_length < sizeof(sQMIMsgHeader))
528    {
529        return -1;
530    }
531 
532    mHeader = (sQMIMsgHeader *)pReadURB->transfer_buffer;
533    if(le16_to_cpu(mHeader->idenity) != MERGE_PACKET_IDENTITY || le16_to_cpu(mHeader->version) != MERGE_PACKET_VERSION || le16_to_cpu(mHeader->cur_len) > le16_to_cpu(mHeader->total_len))
534        return -1;
535 
536    if(le16_to_cpu(mHeader->cur_len) == le16_to_cpu(mHeader->total_len)) {
537         mPacket->len = le16_to_cpu(mHeader->total_len);
538         memcpy(pReadURB->transfer_buffer, pReadURB->transfer_buffer + sizeof(sQMIMsgHeader), mPacket->len);
539         pReadURB->actual_length = mPacket->len;
540         mPacket->len = 0;
541 
542         return 0;
543    }
544 
545    memcpy(mPacket->buf + mPacket->len, pReadURB->transfer_buffer + sizeof(sQMIMsgHeader), le16_to_cpu(mHeader->cur_len));
546    mPacket->len += le16_to_cpu(mHeader->cur_len);
547 
548    if (le16_to_cpu(mHeader->cur_len) < MERGE_PACKET_MAX_PAYLOAD_SIZE || mPacket->len >= le16_to_cpu(mHeader->total_len)) {
549         memcpy(pReadURB->transfer_buffer, mPacket->buf, mPacket->len);
550         pReadURB->actual_length = mPacket->len;
551         mPacket->len = 0;
552         return 0;
553    }
554 
555    return -1;
556 }
557 #endif
558 
559 /*===========================================================================
560 METHOD:
561    ReadCallback (Public Method)
562 
563 DESCRIPTION:
564    Put the data in storage and notify anyone waiting for data
565 
566 PARAMETERS
567    pReadURB       [ I ] - URB this callback is run for
568 
569 RETURN VALUE:
570    None
571 ===========================================================================*/
572 #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 ))
ReadCallback(struct urb * pReadURB)573 static void ReadCallback( struct urb * pReadURB )
574 #else
575 static void ReadCallback(struct urb *pReadURB, struct pt_regs *regs)
576 #endif
577 {
578    int result;
579    u16 clientID;
580    sClientMemList * pClientMem;
581    void * pData;
582    void * pDataCopy;
583    u16 dataSize;
584    sGobiUSBNet * pDev;
585    unsigned long flags;
586    u16 transactionID;
587 
588    if (pReadURB == NULL)
589    {
590       DBG( "bad read URB\n" );
591       return;
592    }
593 
594    pDev = pReadURB->context;
595    if (IsDeviceValid( pDev ) == false)
596    {
597       DBG( "Invalid device!\n" );
598       return;
599    }
600 
601 #ifdef READ_QMI_URB_ERROR
602    del_timer(&pDev->mQMIDev.mReadUrbTimer);
603    if ((pReadURB->status == -ECONNRESET) && (pReadURB->actual_length > 0))
604       pReadURB->status = 0;
605 #endif
606 
607    if (pReadURB->status != 0)
608    {
609       DBG( "Read status = %d\n", pReadURB->status );
610 
611       // Resubmit the interrupt URB
612       ResubmitIntURB( pDev->mQMIDev.mpIntURB );
613 
614       return;
615    }
616    DBG( "Read %d bytes\n", pReadURB->actual_length );
617 
618 #ifdef QUECTEL_QMI_MERGE
619    if(MergeRecQmiMsg(&pDev->mQMIDev, pReadURB))
620    {
621       DBG( "not a full packet, read again\n");
622       // Resubmit the interrupt URB
623       ResubmitIntURB( pDev->mQMIDev.mpIntURB );
624       return;
625    }
626 #endif
627 
628    pData = pReadURB->transfer_buffer;
629    dataSize = pReadURB->actual_length;
630 
631    PrintHex( pData, dataSize );
632 
633 #ifdef READ_QMI_URB_ERROR
634    if (dataSize < (le16_to_cpu(get_unaligned((u16*)(pData + 1))) + 1)) {
635       dataSize = (le16_to_cpu(get_unaligned((u16*)(pData + 1))) + 1);
636       memset(pReadURB->transfer_buffer + pReadURB->actual_length, 0x00, dataSize - pReadURB->actual_length);
637       INFO( "Read %d / %d bytes\n", pReadURB->actual_length, dataSize);
638    }
639 #endif
640 
641    result = ParseQMUX( &clientID,
642                        pData,
643                        dataSize );
644    if (result < 0)
645    {
646       DBG( "Read error parsing QMUX %d\n", result );
647 
648       // Resubmit the interrupt URB
649       ResubmitIntURB( pDev->mQMIDev.mpIntURB );
650 
651       return;
652    }
653 
654    // Grab transaction ID
655 
656    // Data large enough?
657    if (dataSize < result + 3)
658    {
659       DBG( "Data buffer too small to parse\n" );
660 
661       // Resubmit the interrupt URB
662       ResubmitIntURB( pDev->mQMIDev.mpIntURB );
663 
664       return;
665    }
666 
667    // Transaction ID size is 1 for QMICTL, 2 for others
668    if (clientID == QMICTL)
669    {
670       transactionID = *(u8*)(pData + result + 1);
671    }
672    else
673    {
674       transactionID = le16_to_cpu( get_unaligned((u16*)(pData + result + 1)) );
675    }
676 
677    // Critical section
678    spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
679 
680    // Find memory storage for this service and Client ID
681    // Not using FindClientMem because it can't handle broadcasts
682    pClientMem = pDev->mQMIDev.mpClientMemList;
683 
684    while (pClientMem != NULL)
685    {
686       if (pClientMem->mClientID == clientID
687       ||  (pClientMem->mClientID | 0xff00) == clientID)
688       {
689          // Make copy of pData
690          pDataCopy = kmalloc( dataSize, GFP_ATOMIC );
691          if (pDataCopy == NULL)
692          {
693             DBG( "Error allocating client data memory\n" );
694 
695             // End critical section
696             spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
697 
698             // Resubmit the interrupt URB
699             ResubmitIntURB( pDev->mQMIDev.mpIntURB );
700 
701             return;
702          }
703 
704          memcpy( pDataCopy, pData, dataSize );
705 
706          if (AddToReadMemList( pDev,
707                                pClientMem->mClientID,
708                                transactionID,
709                                pDataCopy,
710                                dataSize ) == false)
711          {
712             DBG( "Error allocating pReadMemListEntry "
713                  "read will be discarded\n" );
714             kfree( pDataCopy );
715 
716             // End critical section
717             spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
718 
719             // Resubmit the interrupt URB
720             ResubmitIntURB( pDev->mQMIDev.mpIntURB );
721 
722             return;
723          }
724 
725          // Success
726          VDBG( "Creating new readListEntry for client 0x%04X, TID %x\n",
727               clientID,
728               transactionID );
729 
730          // Notify this client data exists
731          NotifyAndPopNotifyList( pDev,
732                                  pClientMem->mClientID,
733                                  transactionID );
734 
735          // Possibly notify poll() that data exists
736          wake_up_interruptible_sync( &pClientMem->mWaitQueue );
737 
738          // Not a broadcast
739          if (clientID >> 8 != 0xff)
740          {
741             break;
742          }
743       }
744 
745       // Next element
746       pClientMem = pClientMem->mpNext;
747    }
748 
749    // End critical section
750    spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
751 
752    // Resubmit the interrupt URB
753    ResubmitIntURB( pDev->mQMIDev.mpIntURB );
754 }
755 
756 /*===========================================================================
757 METHOD:
758    IntCallback (Public Method)
759 
760 DESCRIPTION:
761    Data is available, fire off a read URB
762 
763 PARAMETERS
764    pIntURB       [ I ] - URB this callback is run for
765 
766 RETURN VALUE:
767    None
768 ===========================================================================*/
769 #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 ))
IntCallback(struct urb * pIntURB)770 static void IntCallback( struct urb * pIntURB )
771 {
772 #else
773 static void IntCallback(struct urb *pIntURB, struct pt_regs *regs)
774 {
775 #endif
776    int status;
777    struct usb_cdc_notification *dr;
778 
779    sGobiUSBNet * pDev = (sGobiUSBNet *)pIntURB->context;
780    dr = (struct usb_cdc_notification *)pDev->mQMIDev.mpIntBuffer;
781 
782    if (IsDeviceValid( pDev ) == false)
783    {
784       DBG( "Invalid device!\n" );
785       return;
786    }
787 
788    // Verify this was a normal interrupt
789    if (pIntURB->status != 0)
790    {
791         DBG( "IntCallback: Int status = %d\n", pIntURB->status );
792 
793       // Ignore EOVERFLOW errors
794       if (pIntURB->status != -EOVERFLOW)
795       {
796          // Read 'thread' dies here
797          return;
798       }
799    }
800    else
801    {
802       //TODO cast transfer_buffer to struct usb_cdc_notification
803 
804       VDBG( "IntCallback: Encapsulated Response = 0x%llx\n",
805           (*(u64*)pIntURB->transfer_buffer));
806 
807      switch (dr->bNotificationType) {
808       case USB_CDC_NOTIFY_RESPONSE_AVAILABLE: //0x01
809          {
810           // Time to read
811           usb_fill_control_urb( pDev->mQMIDev.mpReadURB,
812                              pDev->mpNetDev->udev,
813                              usb_rcvctrlpipe( pDev->mpNetDev->udev, 0 ),
814                              (unsigned char *)pDev->mQMIDev.mpReadSetupPacket,
815                              pDev->mQMIDev.mpReadBuffer,
816                              DEFAULT_READ_URB_LENGTH,
817                              ReadCallback,
818                              pDev );
819           #ifdef READ_QMI_URB_ERROR
820           mod_timer( &pDev->mQMIDev.mReadUrbTimer, jiffies + msecs_to_jiffies(300) );
821           #endif
822           status = usb_submit_urb( pDev->mQMIDev.mpReadURB, GFP_ATOMIC );
823           if (status != 0)
824           {
825             DBG("Error submitting Read URB %d\n", status);
826             // Resubmit the interrupt urb
827             ResubmitIntURB(pIntURB);
828             return;
829           }
830 
831            // Int URB will be resubmitted during ReadCallback
832            return;
833          }
834       case USB_CDC_NOTIFY_SPEED_CHANGE:   //0x2a
835          {
836              DBG( "IntCallback: Connection Speed Change = 0x%llx\n",
837               (*(u64*)pIntURB->transfer_buffer));
838 
839            // if upstream or downstream is 0, stop traffic.  Otherwise resume it
840            if ((*(u32*)(pIntURB->transfer_buffer + 8) == 0)
841            ||  (*(u32*)(pIntURB->transfer_buffer + 12) == 0))
842            {
843               GobiSetDownReason( pDev, CDC_CONNECTION_SPEED );
844               DBG( "traffic stopping due to CONNECTION_SPEED_CHANGE\n" );
845            }
846            else
847            {
848               GobiClearDownReason( pDev, CDC_CONNECTION_SPEED );
849               DBG( "resuming traffic due to CONNECTION_SPEED_CHANGE\n" );
850            }
851          }
852       break;
853       default:
854          {
855              DBG( "ignoring invalid interrupt in packet\n" );
856              PrintHex( pIntURB->transfer_buffer, pIntURB->actual_length );
857          }
858       }
859 
860         // Resubmit the interrupt urb
861       ResubmitIntURB( pIntURB );
862 
863       return;
864    }
865 }
866 
867 #ifdef READ_QMI_URB_ERROR
868 static void ReadUrbTimerFunc( struct urb * pReadURB )
869 {
870   int result;
871 
872   INFO( "%s called (%ld).\n", __func__, jiffies );
873 
874   if ((pReadURB != NULL) && (pReadURB->status == -EINPROGRESS))
875   {
876      // Asynchronously unlink URB. On success, -EINPROGRESS will be returned,
877      // URB status will be set to -ECONNRESET, and ReadCallback() executed
878      result = usb_unlink_urb( pReadURB );
879      INFO( "%s called usb_unlink_urb, result = %d\n", __func__, result);
880   }
881 }
882 #endif
883 
884 /*===========================================================================
885 METHOD:
886    StartRead (Public Method)
887 
888 DESCRIPTION:
889    Start continuous read "thread" (callback driven)
890 
891    Note: In case of error, KillRead() should be run
892          to remove urbs and clean up memory.
893 
894 PARAMETERS:
895    pDev     [ I ] - Device specific memory
896 
897 RETURN VALUE:
898    int - 0 for success
899          negative errno for failure
900 ===========================================================================*/
901 int QuecStartRead( sGobiUSBNet * pDev )
902 {
903    int interval;
904    struct usb_endpoint_descriptor *pendp;
905 
906    if (IsDeviceValid( pDev ) == false)
907    {
908       DBG( "Invalid device!\n" );
909       return -ENXIO;
910    }
911 
912    // Allocate URB buffers
913    pDev->mQMIDev.mpReadURB = usb_alloc_urb( 0, GFP_KERNEL );
914    if (pDev->mQMIDev.mpReadURB == NULL)
915    {
916       DBG( "Error allocating read urb\n" );
917       return -ENOMEM;
918    }
919 
920 #ifdef READ_QMI_URB_ERROR
921    setup_timer( &pDev->mQMIDev.mReadUrbTimer, (void*)ReadUrbTimerFunc, (unsigned long)pDev->mQMIDev.mpReadURB );
922 #endif
923 
924    pDev->mQMIDev.mpIntURB = usb_alloc_urb( 0, GFP_KERNEL );
925    if (pDev->mQMIDev.mpIntURB == NULL)
926    {
927       DBG( "Error allocating int urb\n" );
928       usb_free_urb( pDev->mQMIDev.mpReadURB );
929       pDev->mQMIDev.mpReadURB = NULL;
930       return -ENOMEM;
931    }
932 
933    // Create data buffers
934    pDev->mQMIDev.mpReadBuffer = kmalloc( DEFAULT_READ_URB_LENGTH, GFP_KERNEL );
935    if (pDev->mQMIDev.mpReadBuffer == NULL)
936    {
937       DBG( "Error allocating read buffer\n" );
938       usb_free_urb( pDev->mQMIDev.mpIntURB );
939       pDev->mQMIDev.mpIntURB = NULL;
940       usb_free_urb( pDev->mQMIDev.mpReadURB );
941       pDev->mQMIDev.mpReadURB = NULL;
942       return -ENOMEM;
943    }
944 
945    pDev->mQMIDev.mpIntBuffer = kmalloc( 64, GFP_KERNEL );
946    if (pDev->mQMIDev.mpIntBuffer == NULL)
947    {
948       DBG( "Error allocating int buffer\n" );
949       kfree( pDev->mQMIDev.mpReadBuffer );
950       pDev->mQMIDev.mpReadBuffer = NULL;
951       usb_free_urb( pDev->mQMIDev.mpIntURB );
952       pDev->mQMIDev.mpIntURB = NULL;
953       usb_free_urb( pDev->mQMIDev.mpReadURB );
954       pDev->mQMIDev.mpReadURB = NULL;
955       return -ENOMEM;
956    }
957 
958    pDev->mQMIDev.mpReadSetupPacket = kmalloc( sizeof( sURBSetupPacket ),
959                                               GFP_KERNEL );
960    if (pDev->mQMIDev.mpReadSetupPacket == NULL)
961    {
962       DBG( "Error allocating setup packet buffer\n" );
963       kfree( pDev->mQMIDev.mpIntBuffer );
964       pDev->mQMIDev.mpIntBuffer = NULL;
965       kfree( pDev->mQMIDev.mpReadBuffer );
966       pDev->mQMIDev.mpReadBuffer = NULL;
967       usb_free_urb( pDev->mQMIDev.mpIntURB );
968       pDev->mQMIDev.mpIntURB = NULL;
969       usb_free_urb( pDev->mQMIDev.mpReadURB );
970       pDev->mQMIDev.mpReadURB = NULL;
971       return -ENOMEM;
972    }
973 
974    // CDC Get Encapsulated Response packet
975    pDev->mQMIDev.mpReadSetupPacket->mRequestType = 0xA1;
976    pDev->mQMIDev.mpReadSetupPacket->mRequestCode = 1;
977    pDev->mQMIDev.mpReadSetupPacket->mValue = 0;
978    pDev->mQMIDev.mpReadSetupPacket->mIndex =
979       cpu_to_le16(pDev->mpIntf->cur_altsetting->desc.bInterfaceNumber);  /* interface number */
980    pDev->mQMIDev.mpReadSetupPacket->mLength = cpu_to_le16(DEFAULT_READ_URB_LENGTH);
981 
982    pendp = GetEndpoint(pDev->mpIntf, USB_ENDPOINT_XFER_INT, USB_DIR_IN);
983    if (pendp == NULL)
984    {
985       DBG( "Invalid interrupt endpoint!\n" );
986       kfree(pDev->mQMIDev.mpReadSetupPacket);
987       pDev->mQMIDev.mpReadSetupPacket = NULL;
988       kfree( pDev->mQMIDev.mpIntBuffer );
989       pDev->mQMIDev.mpIntBuffer = NULL;
990       kfree( pDev->mQMIDev.mpReadBuffer );
991       pDev->mQMIDev.mpReadBuffer = NULL;
992       usb_free_urb( pDev->mQMIDev.mpIntURB );
993       pDev->mQMIDev.mpIntURB = NULL;
994       usb_free_urb( pDev->mQMIDev.mpReadURB );
995       pDev->mQMIDev.mpReadURB = NULL;
996       return -ENXIO;
997    }
998 
999 #ifdef QUECTEL_QMI_MERGE
1000    pDev->mQMIDev.mpQmiMsgPacket = kmalloc( sizeof(sQMIMsgPacket), GFP_KERNEL );
1001    if (pDev->mQMIDev.mpQmiMsgPacket == NULL)
1002    {
1003       DBG( "Error allocating qmi msg merge packet buffer!\n" );
1004       kfree(pDev->mQMIDev.mpReadSetupPacket);
1005       pDev->mQMIDev.mpReadSetupPacket = NULL;
1006       kfree( pDev->mQMIDev.mpIntBuffer );
1007       pDev->mQMIDev.mpIntBuffer = NULL;
1008       kfree( pDev->mQMIDev.mpReadBuffer );
1009       pDev->mQMIDev.mpReadBuffer = NULL;
1010       usb_free_urb( pDev->mQMIDev.mpIntURB );
1011       pDev->mQMIDev.mpIntURB = NULL;
1012       usb_free_urb( pDev->mQMIDev.mpReadURB );
1013       pDev->mQMIDev.mpReadURB = NULL;
1014       return -ENOMEM;
1015    }
1016 #endif
1017 
1018    // Interval needs reset after every URB completion
1019    interval = max((int)(pendp->bInterval),
1020                   (pDev->mpNetDev->udev->speed == USB_SPEED_HIGH) ? 7 : 3);
1021 #if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,22 ))
1022     s_interval = interval;
1023 #endif
1024 
1025    // Schedule interrupt URB
1026    usb_fill_int_urb( pDev->mQMIDev.mpIntURB,
1027                      pDev->mpNetDev->udev,
1028                      /* QMI interrupt endpoint for the following
1029                       * interface configuration: DM, NMEA, MDM, NET
1030                       */
1031                      usb_rcvintpipe( pDev->mpNetDev->udev,
1032                                      pendp->bEndpointAddress),
1033                      pDev->mQMIDev.mpIntBuffer,
1034                      min((int)le16_to_cpu(pendp->wMaxPacketSize), 64),
1035                      IntCallback,
1036                      pDev,
1037                      interval );
1038    return usb_submit_urb( pDev->mQMIDev.mpIntURB, GFP_KERNEL );
1039 }
1040 
1041 /*===========================================================================
1042 METHOD:
1043    KillRead (Public Method)
1044 
1045 DESCRIPTION:
1046    Kill continuous read "thread"
1047 
1048 PARAMETERS:
1049    pDev     [ I ] - Device specific memory
1050 
1051 RETURN VALUE:
1052    None
1053 ===========================================================================*/
1054 void QuecKillRead( sGobiUSBNet * pDev )
1055 {
1056    // Stop reading
1057    if (pDev->mQMIDev.mpReadURB != NULL)
1058    {
1059       DBG( "Killng read URB\n" );
1060       usb_kill_urb( pDev->mQMIDev.mpReadURB );
1061    }
1062 
1063    if (pDev->mQMIDev.mpIntURB != NULL)
1064    {
1065       DBG( "Killng int URB\n" );
1066       usb_kill_urb( pDev->mQMIDev.mpIntURB );
1067    }
1068 
1069    // Release buffers
1070    kfree( pDev->mQMIDev.mpReadSetupPacket );
1071    pDev->mQMIDev.mpReadSetupPacket = NULL;
1072    kfree( pDev->mQMIDev.mpReadBuffer );
1073    pDev->mQMIDev.mpReadBuffer = NULL;
1074    kfree( pDev->mQMIDev.mpIntBuffer );
1075    pDev->mQMIDev.mpIntBuffer = NULL;
1076 
1077    // Release URB's
1078    usb_free_urb( pDev->mQMIDev.mpReadURB );
1079    pDev->mQMIDev.mpReadURB = NULL;
1080    usb_free_urb( pDev->mQMIDev.mpIntURB );
1081    pDev->mQMIDev.mpIntURB = NULL;
1082 
1083 #ifdef QUECTEL_QMI_MERGE
1084    kfree( pDev->mQMIDev.mpQmiMsgPacket );
1085    pDev->mQMIDev.mpQmiMsgPacket = NULL;
1086 #endif
1087 }
1088 
1089 /*=========================================================================*/
1090 // Internal read/write functions
1091 /*=========================================================================*/
1092 
1093 /*===========================================================================
1094 METHOD:
1095    ReadAsync (Public Method)
1096 
1097 DESCRIPTION:
1098    Start asynchronous read
1099    NOTE: Reading client's data store, not device
1100 
1101 PARAMETERS:
1102    pDev              [ I ] - Device specific memory
1103    clientID          [ I ] - Requester's client ID
1104    transactionID     [ I ] - Transaction ID or 0 for any
1105    pCallback         [ I ] - Callback to be executed when data is available
1106    pData             [ I ] - Data buffer that willl be passed (unmodified)
1107                              to callback
1108 
1109 RETURN VALUE:
1110    int - 0 for success
1111          negative errno for failure
1112 ===========================================================================*/
1113 static int ReadAsync(
1114    sGobiUSBNet *      pDev,
1115    u16                clientID,
1116    u16                transactionID,
1117    void               (*pCallback)(sGobiUSBNet*, u16, void *),
1118    void *             pData )
1119 {
1120    sClientMemList * pClientMem;
1121    sReadMemList ** ppReadMemList;
1122 
1123    unsigned long flags;
1124 
1125    if (IsDeviceValid( pDev ) == false)
1126    {
1127       DBG( "Invalid device!\n" );
1128       return -ENXIO;
1129    }
1130 
1131    // Critical section
1132    spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1133 
1134    // Find memory storage for this client ID
1135    pClientMem = FindClientMem( pDev, clientID );
1136    if (pClientMem == NULL)
1137    {
1138       DBG( "Could not find matching client ID 0x%04X\n",
1139            clientID );
1140 
1141       // End critical section
1142       spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1143       return -ENXIO;
1144    }
1145 
1146    ppReadMemList = &(pClientMem->mpList);
1147 
1148    // Does data already exist?
1149    while (*ppReadMemList != NULL)
1150    {
1151       // Is this element our data?
1152       if (transactionID == 0
1153       ||  transactionID == (*ppReadMemList)->mTransactionID)
1154       {
1155          // End critical section
1156          spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1157 
1158          // Run our own callback
1159          pCallback( pDev, clientID, pData );
1160 
1161          return 0;
1162       }
1163 
1164       // Next
1165       ppReadMemList = &(*ppReadMemList)->mpNext;
1166    }
1167 
1168    // Data not found, add ourself to list of waiters
1169    if (AddToNotifyList( pDev,
1170                         clientID,
1171                         transactionID,
1172                         pCallback,
1173                         pData ) == false)
1174    {
1175       DBG( "Unable to register for notification\n" );
1176    }
1177 
1178    // End critical section
1179    spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1180 
1181    // Success
1182    return 0;
1183 }
1184 
1185 /*===========================================================================
1186 METHOD:
1187    UpSem (Public Method)
1188 
1189 DESCRIPTION:
1190    Notification function for synchronous read
1191 
1192 PARAMETERS:
1193    pDev              [ I ] - Device specific memory
1194    clientID          [ I ] - Requester's client ID
1195    pData             [ I ] - Buffer that holds semaphore to be up()-ed
1196 
1197 RETURN VALUE:
1198    None
1199 ===========================================================================*/
1200 #define QUEC_SEM_MAGIC 0x12345678
1201 struct QuecSem {
1202     struct semaphore readSem;
1203     int magic;
1204 };
1205 
1206 static void UpSem(
1207    sGobiUSBNet * pDev,
1208    u16             clientID,
1209    void *          pData )
1210 {
1211    struct QuecSem *pSem = (struct QuecSem *)pData;
1212 
1213    VDBG( "0x%04X\n", clientID );
1214 
1215    if (pSem->magic == QUEC_SEM_MAGIC)
1216       up( &(pSem->readSem) );
1217    else
1218        kfree(pSem);
1219    return;
1220 }
1221 
1222 /*===========================================================================
1223 METHOD:
1224    ReadSync (Public Method)
1225 
1226 DESCRIPTION:
1227    Start synchronous read
1228    NOTE: Reading client's data store, not device
1229 
1230 PARAMETERS:
1231    pDev              [ I ] - Device specific memory
1232    ppOutBuffer       [I/O] - On success, will be filled with a
1233                              pointer to read buffer
1234    clientID          [ I ] - Requester's client ID
1235    transactionID     [ I ] - Transaction ID or 0 for any
1236 
1237 RETURN VALUE:
1238    int - size of data read for success
1239          negative errno for failure
1240 ===========================================================================*/
1241 static int ReadSync(
1242    sGobiUSBNet *    pDev,
1243    void **            ppOutBuffer,
1244    u16                clientID,
1245    u16                transactionID )
1246 {
1247    int result;
1248    sClientMemList * pClientMem;
1249    sNotifyList ** ppNotifyList, * pDelNotifyListEntry;
1250    struct QuecSem readSem;
1251    void * pData;
1252    unsigned long flags;
1253    u16 dataSize;
1254 
1255    if (IsDeviceValid( pDev ) == false)
1256    {
1257       DBG( "Invalid device!\n" );
1258       return -ENXIO;
1259    }
1260 
1261    // Critical section
1262    spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1263 
1264    // Find memory storage for this Client ID
1265    pClientMem = FindClientMem( pDev, clientID );
1266    if (pClientMem == NULL)
1267    {
1268       DBG( "Could not find matching client ID 0x%04X\n",
1269            clientID );
1270 
1271       // End critical section
1272       spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1273       return -ENXIO;
1274    }
1275 
1276    // Note: in cases where read is interrupted,
1277    //    this will verify client is still valid
1278    while (PopFromReadMemList( pDev,
1279                               clientID,
1280                               transactionID,
1281                               &pData,
1282                               &dataSize ) == false)
1283    {
1284       // Data does not yet exist, wait
1285       sema_init( &readSem.readSem, 0 );
1286       readSem.magic = QUEC_SEM_MAGIC;
1287 
1288       // Add ourself to list of waiters
1289       if (AddToNotifyList( pDev,
1290                            clientID,
1291                            transactionID,
1292                            UpSem,
1293                            &readSem ) == false)
1294       {
1295          DBG( "unable to register for notification\n" );
1296          spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1297          return -EFAULT;
1298       }
1299 
1300       // End critical section while we block
1301       spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1302 
1303       // Wait for notification
1304       result = down_interruptible( &readSem.readSem );
1305       //if (result) INFO("down_interruptible = %d\n", result);
1306       if (result == -EINTR) {
1307          result = down_timeout(&readSem.readSem, msecs_to_jiffies(200));
1308          //if (result) INFO("down_timeout = %d\n", result);
1309       }
1310       if (result != 0)
1311       {
1312          DBG( "Down Timeout %d\n", result );
1313 
1314          // readSem will fall out of scope,
1315          // remove from notify list so it's not referenced
1316          spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1317          ppNotifyList = &(pClientMem->mpReadNotifyList);
1318          pDelNotifyListEntry = NULL;
1319 
1320          // Find and delete matching entry
1321          while (*ppNotifyList != NULL)
1322          {
1323             if ((*ppNotifyList)->mpData == &readSem)
1324             {
1325                pDelNotifyListEntry = *ppNotifyList;
1326                *ppNotifyList = (*ppNotifyList)->mpNext;
1327                kfree( pDelNotifyListEntry );
1328                break;
1329             }
1330 
1331             // Next
1332             ppNotifyList = &(*ppNotifyList)->mpNext;
1333          }
1334 
1335          spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1336          return -EINTR;
1337       }
1338 
1339       // Verify device is still valid
1340       if (IsDeviceValid( pDev ) == false)
1341       {
1342          DBG( "Invalid device!\n" );
1343          return -ENXIO;
1344       }
1345 
1346       // Restart critical section and continue loop
1347       spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1348    }
1349 
1350    // End Critical section
1351    spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1352 
1353    // Success
1354    *ppOutBuffer = pData;
1355 
1356    return dataSize;
1357 }
1358 
1359 /*===========================================================================
1360 METHOD:
1361    WriteSyncCallback (Public Method)
1362 
1363 DESCRIPTION:
1364    Write callback
1365 
1366 PARAMETERS
1367    pWriteURB       [ I ] - URB this callback is run for
1368 
1369 RETURN VALUE:
1370    None
1371 ===========================================================================*/
1372 #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 ))
1373 static void WriteSyncCallback( struct urb * pWriteURB )
1374 #else
1375 static void WriteSyncCallback(struct urb *pWriteURB, struct pt_regs *regs)
1376 #endif
1377 {
1378    if (pWriteURB == NULL)
1379    {
1380       DBG( "null urb\n" );
1381       return;
1382    }
1383 
1384    DBG( "Write status/size %d/%d\n",
1385         pWriteURB->status,
1386         pWriteURB->actual_length );
1387 
1388    // Notify that write has completed by up()-ing semeaphore
1389    up( (struct semaphore * )pWriteURB->context );
1390 
1391    return;
1392 }
1393 
1394 /*===========================================================================
1395 METHOD:
1396    WriteSync (Public Method)
1397 
1398 DESCRIPTION:
1399    Start synchronous write
1400 
1401 PARAMETERS:
1402    pDev                 [ I ] - Device specific memory
1403    pWriteBuffer         [ I ] - Data to be written
1404    writeBufferSize      [ I ] - Size of data to be written
1405    clientID             [ I ] - Client ID of requester
1406 
1407 RETURN VALUE:
1408    int - write size (includes QMUX)
1409          negative errno for failure
1410 ===========================================================================*/
1411 static int WriteSync(
1412    sGobiUSBNet *          pDev,
1413    char *                 pWriteBuffer,
1414    int                    writeBufferSize,
1415    u16                    clientID )
1416 {
1417    int result;
1418    struct semaphore writeSem;
1419    struct urb * pWriteURB;
1420    sURBSetupPacket *writeSetup;
1421    unsigned long flags;
1422 
1423    if (IsDeviceValid( pDev ) == false)
1424    {
1425       DBG( "Invalid device!\n" );
1426       return -ENXIO;
1427    }
1428 
1429    pWriteURB = usb_alloc_urb( 0, GFP_KERNEL );
1430    if (pWriteURB == NULL)
1431    {
1432       DBG( "URB mem error\n" );
1433       return -ENOMEM;
1434    }
1435 
1436    // Fill writeBuffer with QMUX
1437    result = FillQMUX( clientID, pWriteBuffer, writeBufferSize );
1438    if (result < 0)
1439    {
1440       usb_free_urb( pWriteURB );
1441       return result;
1442    }
1443 
1444    // CDC Send Encapsulated Request packet
1445    writeSetup = kmalloc(sizeof(sURBSetupPacket), GFP_KERNEL);
1446    writeSetup->mRequestType = 0x21;
1447    writeSetup->mRequestCode = 0;
1448    writeSetup->mValue = 0;
1449    writeSetup->mIndex = cpu_to_le16(pDev->mpIntf->cur_altsetting->desc.bInterfaceNumber);
1450    writeSetup->mLength = cpu_to_le16(writeBufferSize);
1451 
1452    // Create URB
1453    usb_fill_control_urb( pWriteURB,
1454                          pDev->mpNetDev->udev,
1455                          usb_sndctrlpipe( pDev->mpNetDev->udev, 0 ),
1456                          (unsigned char *)writeSetup,
1457                          (void*)pWriteBuffer,
1458                          writeBufferSize,
1459                          NULL,
1460                          pDev );
1461 
1462    DBG( "Actual Write:\n" );
1463    PrintHex( pWriteBuffer, writeBufferSize );
1464 
1465    sema_init( &writeSem, 0 );
1466 
1467    pWriteURB->complete = WriteSyncCallback;
1468    pWriteURB->context = &writeSem;
1469 
1470    // Wake device
1471    result = usb_autopm_get_interface( pDev->mpIntf );
1472    if (result < 0)
1473    {
1474       DBG( "unable to resume interface: %d\n", result );
1475 
1476       // Likely caused by device going from autosuspend -> full suspend
1477       if (result == -EPERM)
1478       {
1479 #ifdef CONFIG_PM
1480 #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,33 ))
1481 #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 ))
1482          pDev->mpNetDev->udev->auto_pm = 0;
1483 #endif
1484 #endif
1485          QuecGobiNetSuspend( pDev->mpIntf, PMSG_SUSPEND );
1486 #endif /* CONFIG_PM */
1487       }
1488       usb_free_urb( pWriteURB );
1489       kfree(writeSetup);
1490 
1491       return result;
1492    }
1493 
1494    // Critical section
1495    spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1496 
1497    if (AddToURBList( pDev, clientID, pWriteURB ) == false)
1498    {
1499       usb_free_urb( pWriteURB );
1500       kfree(writeSetup);
1501 
1502       // End critical section
1503       spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1504       usb_autopm_put_interface( pDev->mpIntf );
1505       return -EINVAL;
1506    }
1507 
1508    spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1509    result = usb_submit_urb( pWriteURB, GFP_KERNEL );
1510    spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1511 
1512    if (result < 0)
1513    {
1514       DBG( "submit URB error %d\n", result );
1515 
1516       // Get URB back so we can destroy it
1517       if (PopFromURBList( pDev, clientID ) != pWriteURB)
1518       {
1519          // This shouldn't happen
1520          DBG( "Didn't get write URB back\n" );
1521          //advoid ReleaseClientID() free again (no PopFromURBList)
1522       }
1523       else
1524       {
1525       usb_free_urb( pWriteURB );
1526       kfree(writeSetup);
1527       }
1528 
1529       // End critical section
1530       spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1531       usb_autopm_put_interface( pDev->mpIntf );
1532       return result;
1533    }
1534 
1535    // End critical section while we block
1536    spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1537 
1538    // Wait for write to finish
1539    if (1 != 0) //(interruptible != 0)
1540    {
1541       // Allow user interrupts
1542       result = down_interruptible( &writeSem );
1543       //if (result) INFO("down_interruptible = %d\n", result);
1544       if (result == -EINTR) {
1545          result = down_timeout(&writeSem, msecs_to_jiffies(200));
1546          //if (result) INFO("down_interruptible = %d\n", result);
1547       }
1548    }
1549    else
1550    {
1551       // Ignore user interrupts
1552       result = 0;
1553       down( &writeSem );
1554    }
1555 
1556    // Write is done, release device
1557    usb_autopm_put_interface( pDev->mpIntf );
1558 
1559    // Verify device is still valid
1560    if (IsDeviceValid( pDev ) == false)
1561    {
1562       DBG( "Invalid device!\n" );
1563 
1564       usb_kill_urb( pWriteURB );
1565 #if 0 //advoid ReleaseClientID() free again (no PopFromURBList)
1566       usb_free_urb( pWriteURB );
1567       kfree(writeSetup);
1568 #endif
1569       return -ENXIO;
1570    }
1571 
1572    // Restart critical section
1573    spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1574 
1575    // Get URB back so we can destroy it
1576    if (PopFromURBList( pDev, clientID ) != pWriteURB)
1577    {
1578       // This shouldn't happen
1579       DBG( "Didn't get write URB back\n" );
1580 
1581       // End critical section
1582       spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1583       usb_kill_urb( pWriteURB );
1584 #if 0 //advoid ReleaseClientID() free again (fail PopFromURBList)
1585       usb_free_urb( pWriteURB );
1586       kfree(writeSetup);
1587 #endif
1588       return -EINVAL;
1589    }
1590 
1591    // End critical section
1592    spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1593 
1594    if (result == 0)
1595    {
1596       // Write is finished
1597       if (pWriteURB->status == 0)
1598       {
1599          // Return number of bytes that were supposed to have been written,
1600          //   not size of QMI request
1601          result = writeBufferSize;
1602       }
1603       else
1604       {
1605          DBG( "bad status = %d\n", pWriteURB->status );
1606 
1607          // Return error value
1608          result = pWriteURB->status;
1609       }
1610    }
1611    else
1612    {
1613       // We have been forcibly interrupted
1614       DBG( "Interrupted %d !!!\n", result );
1615       DBG( "Device may be in bad state and need reset !!!\n" );
1616 
1617       // URB has not finished
1618       usb_kill_urb( pWriteURB );
1619    }
1620 
1621    usb_free_urb( pWriteURB );
1622    kfree(writeSetup);
1623 
1624    return result;
1625 }
1626 
1627 /*=========================================================================*/
1628 // Internal memory management functions
1629 /*=========================================================================*/
1630 
1631 /*===========================================================================
1632 METHOD:
1633    GetClientID (Public Method)
1634 
1635 DESCRIPTION:
1636    Request a QMI client for the input service type and initialize memory
1637    structure
1638 
1639 PARAMETERS:
1640    pDev           [ I ] - Device specific memory
1641    serviceType    [ I ] - Desired QMI service type
1642 
1643 RETURN VALUE:
1644    int - Client ID for success (positive)
1645          Negative errno for error
1646 ===========================================================================*/
1647 static int GetClientID(
1648    sGobiUSBNet *      pDev,
1649    u8                 serviceType )
1650 {
1651    u16 clientID;
1652    sClientMemList ** ppClientMem;
1653    int result;
1654    void * pWriteBuffer;
1655    u16 writeBufferSize;
1656    void * pReadBuffer;
1657    u16 readBufferSize;
1658    unsigned long flags;
1659    u8 transactionID;
1660 
1661    if (IsDeviceValid( pDev ) == false)
1662    {
1663       DBG( "Invalid device!\n" );
1664       return -ENXIO;
1665    }
1666 
1667    // Run QMI request to be asigned a Client ID
1668    if (serviceType != 0)
1669    {
1670       writeBufferSize = QMICTLGetClientIDReqSize();
1671       pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
1672       if (pWriteBuffer == NULL)
1673       {
1674          return -ENOMEM;
1675       }
1676 
1677       transactionID = QMIXactionIDGet( pDev );
1678 
1679       result = QMICTLGetClientIDReq( pWriteBuffer,
1680                                      writeBufferSize,
1681                                      transactionID,
1682                                      serviceType );
1683       if (result < 0)
1684       {
1685          kfree( pWriteBuffer );
1686          return result;
1687       }
1688 
1689 
1690       result = WriteSync( pDev,
1691                           pWriteBuffer,
1692                           writeBufferSize,
1693                           QMICTL );
1694       kfree( pWriteBuffer );
1695 
1696       if (result < 0)
1697       {
1698          return result;
1699       }
1700 
1701       result = ReadSync( pDev,
1702                          &pReadBuffer,
1703                          QMICTL,
1704                          transactionID );
1705       if (result < 0)
1706       {
1707          DBG( "bad read data %d\n", result );
1708          return result;
1709       }
1710       readBufferSize = result;
1711 
1712       result = QMICTLGetClientIDResp( pReadBuffer,
1713                                       readBufferSize,
1714                                       &clientID );
1715 
1716      /* Upon return from QMICTLGetClientIDResp, clientID
1717       * low address contains the Service Number (SN), and
1718       * clientID high address contains Client Number (CN)
1719       * For the ReadCallback to function correctly,we swap
1720       * the SN and CN on a Big Endian architecture.
1721       */
1722       clientID = le16_to_cpu(clientID);
1723 
1724       kfree( pReadBuffer );
1725 
1726       if (result < 0)
1727       {
1728          return result;
1729       }
1730    }
1731    else
1732    {
1733       // QMI CTL will always have client ID 0
1734       clientID = 0;
1735    }
1736 
1737    // Critical section
1738    spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1739 
1740    // Verify client is not already allocated
1741    if (FindClientMem( pDev, clientID ) != NULL)
1742    {
1743       DBG( "Client memory already exists\n" );
1744 
1745       // End Critical section
1746       spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1747       return -ETOOMANYREFS;
1748    }
1749 
1750    // Go to last entry in client mem list
1751    ppClientMem = &pDev->mQMIDev.mpClientMemList;
1752    while (*ppClientMem != NULL)
1753    {
1754       ppClientMem = &(*ppClientMem)->mpNext;
1755    }
1756 
1757    // Create locations for read to place data into
1758    *ppClientMem = kmalloc( sizeof( sClientMemList ), GFP_ATOMIC );
1759    if (*ppClientMem == NULL)
1760    {
1761       DBG( "Error allocating read list\n" );
1762 
1763       // End critical section
1764       spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1765       return -ENOMEM;
1766    }
1767 
1768    (*ppClientMem)->mClientID = clientID;
1769    (*ppClientMem)->mpList = NULL;
1770    (*ppClientMem)->mpReadNotifyList = NULL;
1771    (*ppClientMem)->mpURBList = NULL;
1772    (*ppClientMem)->mpNext = NULL;
1773 
1774    // Initialize workqueue for poll()
1775    init_waitqueue_head( &(*ppClientMem)->mWaitQueue );
1776 
1777    // End Critical section
1778    spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1779 
1780    return (int)( (*ppClientMem)->mClientID );
1781 }
1782 
1783 /*===========================================================================
1784 METHOD:
1785    ReleaseClientID (Public Method)
1786 
1787 DESCRIPTION:
1788    Release QMI client and free memory
1789 
1790 PARAMETERS:
1791    pDev           [ I ] - Device specific memory
1792    clientID       [ I ] - Requester's client ID
1793 
1794 RETURN VALUE:
1795    None
1796 ===========================================================================*/
1797 static void ReleaseClientID(
1798    sGobiUSBNet *    pDev,
1799    u16                clientID )
1800 {
1801    int result;
1802    sClientMemList ** ppDelClientMem;
1803    sClientMemList * pNextClientMem;
1804    struct urb * pDelURB;
1805    void * pDelData;
1806    u16 dataSize;
1807    void * pWriteBuffer;
1808    u16 writeBufferSize;
1809    void * pReadBuffer;
1810    u16 readBufferSize;
1811    unsigned long flags;
1812    u8 transactionID;
1813 
1814    // Is device is still valid?
1815    if (IsDeviceValid( pDev ) == false)
1816    {
1817       DBG( "invalid device\n" );
1818       return;
1819    }
1820 
1821    DBG( "releasing 0x%04X\n", clientID );
1822 
1823    // Run QMI ReleaseClientID if this isn't QMICTL
1824    if (clientID != QMICTL && pDev->mpNetDev->udev->state)
1825    {
1826       // Note: all errors are non fatal, as we always want to delete
1827       //    client memory in latter part of function
1828 
1829       writeBufferSize = QMICTLReleaseClientIDReqSize();
1830       pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
1831       if (pWriteBuffer == NULL)
1832       {
1833          DBG( "memory error\n" );
1834       }
1835       else
1836       {
1837          transactionID = QMIXactionIDGet( pDev );
1838 
1839          result = QMICTLReleaseClientIDReq( pWriteBuffer,
1840                                             writeBufferSize,
1841                                             transactionID,
1842                                             clientID );
1843          if (result < 0)
1844          {
1845             kfree( pWriteBuffer );
1846             DBG( "error %d filling req buffer\n", result );
1847          }
1848          else
1849          {
1850             result = WriteSync( pDev,
1851                                 pWriteBuffer,
1852                                 writeBufferSize,
1853                                 QMICTL );
1854             kfree( pWriteBuffer );
1855 
1856             if (result < 0)
1857             {
1858                DBG( "bad write status %d\n", result );
1859             }
1860             else
1861             {
1862                result = ReadSync( pDev,
1863                                   &pReadBuffer,
1864                                   QMICTL,
1865                                   transactionID );
1866                if (result < 0)
1867                {
1868                   DBG( "bad read status %d\n", result );
1869                }
1870                else
1871                {
1872                   readBufferSize = result;
1873 
1874                   result = QMICTLReleaseClientIDResp( pReadBuffer,
1875                                                       readBufferSize );
1876                   kfree( pReadBuffer );
1877 
1878                   if (result < 0)
1879                   {
1880                      DBG( "error %d parsing response\n", result );
1881                   }
1882                }
1883             }
1884          }
1885       }
1886    }
1887 
1888    // Cleaning up client memory
1889 
1890    // Critical section
1891    spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1892 
1893    // Can't use FindClientMem, I need to keep pointer of previous
1894    ppDelClientMem = &pDev->mQMIDev.mpClientMemList;
1895    while (*ppDelClientMem != NULL)
1896    {
1897       if ((*ppDelClientMem)->mClientID == clientID)
1898       {
1899          pNextClientMem = (*ppDelClientMem)->mpNext;
1900 
1901          // Notify all clients
1902          while (NotifyAndPopNotifyList( pDev,
1903                                         clientID,
1904                                         0 ) == true );
1905 
1906          // Kill and free all URB's
1907          pDelURB = PopFromURBList( pDev, clientID );
1908          while (pDelURB != NULL)
1909          {
1910             spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1911             usb_kill_urb( pDelURB );
1912             usb_free_urb( pDelURB );
1913             spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1914             pDelURB = PopFromURBList( pDev, clientID );
1915          }
1916 
1917          // Free any unread data
1918          while (PopFromReadMemList( pDev,
1919                                     clientID,
1920                                     0,
1921                                     &pDelData,
1922                                     &dataSize ) == true )
1923          {
1924             kfree( pDelData );
1925          }
1926 
1927          // Delete client Mem
1928          if (!waitqueue_active( &(*ppDelClientMem)->mWaitQueue))
1929             kfree( *ppDelClientMem );
1930          else
1931             INFO("memory leak!\n");
1932 
1933          // Overwrite the pointer that was to this client mem
1934          *ppDelClientMem = pNextClientMem;
1935       }
1936       else
1937       {
1938          // I now point to (a pointer of ((the node I was at)'s mpNext))
1939          ppDelClientMem = &(*ppDelClientMem)->mpNext;
1940       }
1941    }
1942 
1943    // End Critical section
1944    spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1945 
1946    return;
1947 }
1948 
1949 /*===========================================================================
1950 METHOD:
1951    FindClientMem (Public Method)
1952 
1953 DESCRIPTION:
1954    Find this client's memory
1955 
1956    Caller MUST have lock on mClientMemLock
1957 
1958 PARAMETERS:
1959    pDev           [ I ] - Device specific memory
1960    clientID       [ I ] - Requester's client ID
1961 
1962 RETURN VALUE:
1963    sClientMemList - Pointer to requested sClientMemList for success
1964                     NULL for error
1965 ===========================================================================*/
1966 static sClientMemList * FindClientMem(
1967    sGobiUSBNet *      pDev,
1968    u16              clientID )
1969 {
1970    sClientMemList * pClientMem;
1971 
1972    if (IsDeviceValid( pDev ) == false)
1973    {
1974       DBG( "Invalid device\n" );
1975       return NULL;
1976    }
1977 
1978 #ifdef CONFIG_SMP
1979    // Verify Lock
1980    if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0)
1981    {
1982       DBG( "unlocked\n" );
1983       BUG();
1984    }
1985 #endif
1986 
1987    pClientMem = pDev->mQMIDev.mpClientMemList;
1988    while (pClientMem != NULL)
1989    {
1990       if (pClientMem->mClientID == clientID)
1991       {
1992          // Success
1993          VDBG("Found client's 0x%x memory\n", clientID);
1994          return pClientMem;
1995       }
1996 
1997       pClientMem = pClientMem->mpNext;
1998    }
1999 
2000    DBG( "Could not find client mem 0x%04X\n", clientID );
2001    return NULL;
2002 }
2003 
2004 /*===========================================================================
2005 METHOD:
2006    AddToReadMemList (Public Method)
2007 
2008 DESCRIPTION:
2009    Add Data to this client's ReadMem list
2010 
2011    Caller MUST have lock on mClientMemLock
2012 
2013 PARAMETERS:
2014    pDev           [ I ] - Device specific memory
2015    clientID       [ I ] - Requester's client ID
2016    transactionID  [ I ] - Transaction ID or 0 for any
2017    pData          [ I ] - Data to add
2018    dataSize       [ I ] - Size of data to add
2019 
2020 RETURN VALUE:
2021    bool
2022 ===========================================================================*/
2023 static bool AddToReadMemList(
2024    sGobiUSBNet *      pDev,
2025    u16              clientID,
2026    u16              transactionID,
2027    void *           pData,
2028    u16              dataSize )
2029 {
2030    sClientMemList * pClientMem;
2031    sReadMemList ** ppThisReadMemList;
2032 
2033 #ifdef CONFIG_SMP
2034    // Verify Lock
2035    if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0)
2036    {
2037       DBG( "unlocked\n" );
2038       BUG();
2039    }
2040 #endif
2041 
2042    // Get this client's memory location
2043    pClientMem = FindClientMem( pDev, clientID );
2044    if (pClientMem == NULL)
2045    {
2046       DBG( "Could not find this client's memory 0x%04X\n",
2047            clientID );
2048 
2049       return false;
2050    }
2051 
2052    // Go to last ReadMemList entry
2053    ppThisReadMemList = &pClientMem->mpList;
2054    while (*ppThisReadMemList != NULL)
2055    {
2056       ppThisReadMemList = &(*ppThisReadMemList)->mpNext;
2057    }
2058 
2059    *ppThisReadMemList = kmalloc( sizeof( sReadMemList ), GFP_ATOMIC );
2060    if (*ppThisReadMemList == NULL)
2061    {
2062       DBG( "Mem error\n" );
2063 
2064       return false;
2065    }
2066 
2067    (*ppThisReadMemList)->mpNext = NULL;
2068    (*ppThisReadMemList)->mpData = pData;
2069    (*ppThisReadMemList)->mDataSize = dataSize;
2070    (*ppThisReadMemList)->mTransactionID = transactionID;
2071 
2072    return true;
2073 }
2074 
2075 /*===========================================================================
2076 METHOD:
2077    PopFromReadMemList (Public Method)
2078 
2079 DESCRIPTION:
2080    Remove data from this client's ReadMem list if it matches
2081    the specified transaction ID.
2082 
2083    Caller MUST have lock on mClientMemLock
2084 
2085 PARAMETERS:
2086    pDev              [ I ] - Device specific memory
2087    clientID          [ I ] - Requester's client ID
2088    transactionID     [ I ] - Transaction ID or 0 for any
2089    ppData            [I/O] - On success, will be filled with a
2090                              pointer to read buffer
2091    pDataSize         [I/O] - On succces, will be filled with the
2092                              read buffer's size
2093 
2094 RETURN VALUE:
2095    bool
2096 ===========================================================================*/
2097 static bool PopFromReadMemList(
2098    sGobiUSBNet *      pDev,
2099    u16                  clientID,
2100    u16                  transactionID,
2101    void **              ppData,
2102    u16 *                pDataSize )
2103 {
2104    sClientMemList * pClientMem;
2105    sReadMemList * pDelReadMemList, ** ppReadMemList;
2106 
2107 #ifdef CONFIG_SMP
2108    // Verify Lock
2109    if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0)
2110    {
2111       DBG( "unlocked\n" );
2112       BUG();
2113    }
2114 #endif
2115 
2116    // Get this client's memory location
2117    pClientMem = FindClientMem( pDev, clientID );
2118    if (pClientMem == NULL)
2119    {
2120       DBG( "Could not find this client's memory 0x%04X\n",
2121            clientID );
2122 
2123       return false;
2124    }
2125 
2126    ppReadMemList = &(pClientMem->mpList);
2127    pDelReadMemList = NULL;
2128 
2129    // Find first message that matches this transaction ID
2130    while (*ppReadMemList != NULL)
2131    {
2132       // Do we care about transaction ID?
2133       if (transactionID == 0
2134       ||  transactionID == (*ppReadMemList)->mTransactionID )
2135       {
2136          pDelReadMemList = *ppReadMemList;
2137          VDBG(  "*ppReadMemList = 0x%p pDelReadMemList = 0x%p\n",
2138                *ppReadMemList, pDelReadMemList );
2139          break;
2140       }
2141 
2142       VDBG( "skipping 0x%04X data TID = %x\n", clientID, (*ppReadMemList)->mTransactionID );
2143 
2144       // Next
2145       ppReadMemList = &(*ppReadMemList)->mpNext;
2146    }
2147    VDBG(  "*ppReadMemList = 0x%p pDelReadMemList = 0x%p\n",
2148          *ppReadMemList, pDelReadMemList );
2149    if (pDelReadMemList != NULL)
2150    {
2151       *ppReadMemList = (*ppReadMemList)->mpNext;
2152 
2153       // Copy to output
2154       *ppData = pDelReadMemList->mpData;
2155       *pDataSize = pDelReadMemList->mDataSize;
2156       VDBG(  "*ppData = 0x%p pDataSize = %u\n",
2157             *ppData, *pDataSize );
2158 
2159       // Free memory
2160       kfree( pDelReadMemList );
2161 
2162       return true;
2163    }
2164    else
2165    {
2166       DBG( "No read memory to pop, Client 0x%04X, TID = %x\n",
2167            clientID,
2168            transactionID );
2169       return false;
2170    }
2171 }
2172 
2173 /*===========================================================================
2174 METHOD:
2175    AddToNotifyList (Public Method)
2176 
2177 DESCRIPTION:
2178    Add Notify entry to this client's notify List
2179 
2180    Caller MUST have lock on mClientMemLock
2181 
2182 PARAMETERS:
2183    pDev              [ I ] - Device specific memory
2184    clientID          [ I ] - Requester's client ID
2185    transactionID     [ I ] - Transaction ID or 0 for any
2186    pNotifyFunct      [ I ] - Callback function to be run when data is available
2187    pData             [ I ] - Data buffer that willl be passed (unmodified)
2188                              to callback
2189 
2190 RETURN VALUE:
2191    bool
2192 ===========================================================================*/
2193 static bool AddToNotifyList(
2194    sGobiUSBNet *      pDev,
2195    u16                  clientID,
2196    u16                  transactionID,
2197    void                 (* pNotifyFunct)(sGobiUSBNet *, u16, void *),
2198    void *               pData )
2199 {
2200    sClientMemList * pClientMem;
2201    sNotifyList ** ppThisNotifyList;
2202 
2203 #ifdef CONFIG_SMP
2204    // Verify Lock
2205    if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0)
2206    {
2207       DBG( "unlocked\n" );
2208       BUG();
2209    }
2210 #endif
2211 
2212    // Get this client's memory location
2213    pClientMem = FindClientMem( pDev, clientID );
2214    if (pClientMem == NULL)
2215    {
2216       DBG( "Could not find this client's memory 0x%04X\n", clientID );
2217       return false;
2218    }
2219 
2220    // Go to last URBList entry
2221    ppThisNotifyList = &pClientMem->mpReadNotifyList;
2222    while (*ppThisNotifyList != NULL)
2223    {
2224       ppThisNotifyList = &(*ppThisNotifyList)->mpNext;
2225    }
2226 
2227    *ppThisNotifyList = kmalloc( sizeof( sNotifyList ), GFP_ATOMIC );
2228    if (*ppThisNotifyList == NULL)
2229    {
2230       DBG( "Mem error\n" );
2231       return false;
2232    }
2233 
2234    (*ppThisNotifyList)->mpNext = NULL;
2235    (*ppThisNotifyList)->mpNotifyFunct = pNotifyFunct;
2236    (*ppThisNotifyList)->mpData = pData;
2237    (*ppThisNotifyList)->mTransactionID = transactionID;
2238 
2239    return true;
2240 }
2241 
2242 /*===========================================================================
2243 METHOD:
2244    NotifyAndPopNotifyList (Public Method)
2245 
2246 DESCRIPTION:
2247    Remove first Notify entry from this client's notify list
2248    and Run function
2249 
2250    Caller MUST have lock on mClientMemLock
2251 
2252 PARAMETERS:
2253    pDev              [ I ] - Device specific memory
2254    clientID          [ I ] - Requester's client ID
2255    transactionID     [ I ] - Transaction ID or 0 for any
2256 
2257 RETURN VALUE:
2258    bool
2259 ===========================================================================*/
2260 static bool NotifyAndPopNotifyList(
2261    sGobiUSBNet *        pDev,
2262    u16                  clientID,
2263    u16                  transactionID )
2264 {
2265    sClientMemList * pClientMem;
2266    sNotifyList * pDelNotifyList, ** ppNotifyList;
2267 
2268 #ifdef CONFIG_SMP
2269    // Verify Lock
2270    if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0)
2271    {
2272       DBG( "unlocked\n" );
2273       BUG();
2274    }
2275 #endif
2276 
2277    // Get this client's memory location
2278    pClientMem = FindClientMem( pDev, clientID );
2279    if (pClientMem == NULL)
2280    {
2281       DBG( "Could not find this client's memory 0x%04X\n", clientID );
2282       return false;
2283    }
2284 
2285    ppNotifyList = &(pClientMem->mpReadNotifyList);
2286    pDelNotifyList = NULL;
2287 
2288    // Remove from list
2289    while (*ppNotifyList != NULL)
2290    {
2291       // Do we care about transaction ID?
2292       if (transactionID == 0
2293       ||  (*ppNotifyList)->mTransactionID == 0
2294       ||  transactionID == (*ppNotifyList)->mTransactionID)
2295       {
2296          pDelNotifyList = *ppNotifyList;
2297          break;
2298       }
2299 
2300       DBG( "skipping data TID = %x\n", (*ppNotifyList)->mTransactionID );
2301 
2302       // next
2303       ppNotifyList = &(*ppNotifyList)->mpNext;
2304    }
2305 
2306    if (pDelNotifyList != NULL)
2307    {
2308       // Remove element
2309       *ppNotifyList = (*ppNotifyList)->mpNext;
2310 
2311       // Run notification function
2312       if (pDelNotifyList->mpNotifyFunct != NULL)
2313       {
2314          // Unlock for callback
2315          spin_unlock( &pDev->mQMIDev.mClientMemLock );
2316 
2317          pDelNotifyList->mpNotifyFunct( pDev,
2318                                         clientID,
2319                                         pDelNotifyList->mpData );
2320 
2321          // Restore lock
2322          spin_lock( &pDev->mQMIDev.mClientMemLock );
2323       }
2324 
2325       // Delete memory
2326       kfree( pDelNotifyList );
2327 
2328       return true;
2329    }
2330    else
2331    {
2332       DBG( "no one to notify for TID %x\n", transactionID );
2333 
2334       return false;
2335    }
2336 }
2337 
2338 /*===========================================================================
2339 METHOD:
2340    AddToURBList (Public Method)
2341 
2342 DESCRIPTION:
2343    Add URB to this client's URB list
2344 
2345    Caller MUST have lock on mClientMemLock
2346 
2347 PARAMETERS:
2348    pDev              [ I ] - Device specific memory
2349    clientID          [ I ] - Requester's client ID
2350    pURB              [ I ] - URB to be added
2351 
2352 RETURN VALUE:
2353    bool
2354 ===========================================================================*/
2355 static bool AddToURBList(
2356    sGobiUSBNet *      pDev,
2357    u16                  clientID,
2358    struct urb *     pURB )
2359 {
2360    sClientMemList * pClientMem;
2361    sURBList ** ppThisURBList;
2362 
2363 #ifdef CONFIG_SMP
2364    // Verify Lock
2365    if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0)
2366    {
2367       DBG( "unlocked\n" );
2368       BUG();
2369    }
2370 #endif
2371 
2372    // Get this client's memory location
2373    pClientMem = FindClientMem( pDev, clientID );
2374    if (pClientMem == NULL)
2375    {
2376       DBG( "Could not find this client's memory 0x%04X\n", clientID );
2377       return false;
2378    }
2379 
2380    // Go to last URBList entry
2381    ppThisURBList = &pClientMem->mpURBList;
2382    while (*ppThisURBList != NULL)
2383    {
2384       ppThisURBList = &(*ppThisURBList)->mpNext;
2385    }
2386 
2387    *ppThisURBList = kmalloc( sizeof( sURBList ), GFP_ATOMIC );
2388    if (*ppThisURBList == NULL)
2389    {
2390       DBG( "Mem error\n" );
2391       return false;
2392    }
2393 
2394    (*ppThisURBList)->mpNext = NULL;
2395    (*ppThisURBList)->mpURB = pURB;
2396 
2397    return true;
2398 }
2399 
2400 /*===========================================================================
2401 METHOD:
2402    PopFromURBList (Public Method)
2403 
2404 DESCRIPTION:
2405    Remove URB from this client's URB list
2406 
2407    Caller MUST have lock on mClientMemLock
2408 
2409 PARAMETERS:
2410    pDev           [ I ] - Device specific memory
2411    clientID       [ I ] - Requester's client ID
2412 
2413 RETURN VALUE:
2414    struct urb - Pointer to requested client's URB
2415                 NULL for error
2416 ===========================================================================*/
2417 static struct urb * PopFromURBList(
2418    sGobiUSBNet *      pDev,
2419    u16                  clientID )
2420 {
2421    sClientMemList * pClientMem;
2422    sURBList * pDelURBList;
2423    struct urb * pURB;
2424 
2425 #ifdef CONFIG_SMP
2426    // Verify Lock
2427    if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0)
2428    {
2429       DBG( "unlocked\n" );
2430       BUG();
2431    }
2432 #endif
2433 
2434    // Get this client's memory location
2435    pClientMem = FindClientMem( pDev, clientID );
2436    if (pClientMem == NULL)
2437    {
2438       DBG( "Could not find this client's memory 0x%04X\n", clientID );
2439       return NULL;
2440    }
2441 
2442    // Remove from list
2443    if (pClientMem->mpURBList != NULL)
2444    {
2445       pDelURBList = pClientMem->mpURBList;
2446       pClientMem->mpURBList = pClientMem->mpURBList->mpNext;
2447 
2448       // Copy to output
2449       pURB = pDelURBList->mpURB;
2450 
2451       // Delete memory
2452       kfree( pDelURBList );
2453 
2454       return pURB;
2455    }
2456    else
2457    {
2458       DBG( "No URB's to pop\n" );
2459 
2460       return NULL;
2461    }
2462 }
2463 
2464 #if (LINUX_VERSION_CODE >= KERNEL_VERSION( 3,19,0 ))
2465 #ifndef f_dentry
2466 #define f_dentry f_path.dentry
2467 #endif
2468 #endif
2469 
2470 /*=========================================================================*/
2471 // Internal userspace wrappers
2472 /*=========================================================================*/
2473 
2474 /*===========================================================================
2475 METHOD:
2476    UserspaceunlockedIOCTL (Public Method)
2477 
2478 DESCRIPTION:
2479    Internal wrapper for Userspace IOCTL interface
2480 
2481 PARAMETERS
2482    pFilp        [ I ] - userspace file descriptor
2483    cmd          [ I ] - IOCTL command
2484    arg          [ I ] - IOCTL argument
2485 
2486 RETURN VALUE:
2487    long - 0 for success
2488          Negative errno for failure
2489 ===========================================================================*/
2490 static long UserspaceunlockedIOCTL(
2491    struct file *     pFilp,
2492    unsigned int      cmd,
2493    unsigned long     arg )
2494 {
2495    int result;
2496    u32 devVIDPID;
2497 
2498    sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data;
2499 
2500    if (pFilpData == NULL)
2501    {
2502       DBG( "Bad file data\n" );
2503       return -EBADF;
2504    }
2505 
2506    if (IsDeviceValid( pFilpData->mpDev ) == false)
2507    {
2508       DBG( "Invalid device! Updating f_ops\n" );
2509       pFilp->f_op = pFilp->f_dentry->d_inode->i_fop;
2510       return -ENXIO;
2511    }
2512 
2513    switch (cmd)
2514    {
2515       case IOCTL_QMI_GET_SERVICE_FILE:
2516          DBG( "Setting up QMI for service %lu\n", arg );
2517          if ((u8)arg == 0)
2518          {
2519             DBG( "Cannot use QMICTL from userspace\n" );
2520             return -EINVAL;
2521          }
2522 
2523          // Connection is already setup
2524          if (pFilpData->mClientID != (u16)-1)
2525          {
2526             DBG( "Close the current connection before opening a new one\n" );
2527             return -EBADR;
2528          }
2529 
2530          result = GetClientID( pFilpData->mpDev, (u8)arg );
2531 // it seems QMIWDA only allow one client, if the last quectel-CM donot realese it (killed by SIGKILL).
2532 // can force release it at here
2533 #if 1
2534          if (result < 0 && (u8)arg == QMIWDA)
2535          {
2536              ReleaseClientID( pFilpData->mpDev, QMIWDA | (1 << 8) );
2537              result = GetClientID( pFilpData->mpDev, (u8)arg );
2538          }
2539 #endif
2540          if (result < 0)
2541          {
2542             return result;
2543          }
2544          pFilpData->mClientID = (u16)result;
2545          DBG("pFilpData->mClientID = 0x%x\n", pFilpData->mClientID );
2546          return 0;
2547          break;
2548 
2549 
2550       case IOCTL_QMI_GET_DEVICE_VIDPID:
2551          if (arg == 0)
2552          {
2553             DBG( "Bad VIDPID buffer\n" );
2554             return -EINVAL;
2555          }
2556 
2557          // Extra verification
2558          if (pFilpData->mpDev->mpNetDev == 0)
2559          {
2560             DBG( "Bad mpNetDev\n" );
2561             return -ENOMEM;
2562          }
2563          if (pFilpData->mpDev->mpNetDev->udev == 0)
2564          {
2565             DBG( "Bad udev\n" );
2566             return -ENOMEM;
2567          }
2568 
2569          devVIDPID = ((le16_to_cpu( pFilpData->mpDev->mpNetDev->udev->descriptor.idVendor ) << 16)
2570                      + le16_to_cpu( pFilpData->mpDev->mpNetDev->udev->descriptor.idProduct ) );
2571 
2572          result = copy_to_user( (unsigned int *)arg, &devVIDPID, 4 );
2573          if (result != 0)
2574          {
2575             DBG( "Copy to userspace failure %d\n", result );
2576          }
2577 
2578          return result;
2579 
2580          break;
2581 
2582       case IOCTL_QMI_GET_DEVICE_MEID:
2583          if (arg == 0)
2584          {
2585             DBG( "Bad MEID buffer\n" );
2586             return -EINVAL;
2587          }
2588 
2589          result = copy_to_user( (unsigned int *)arg, &pFilpData->mpDev->mMEID[0], 14 );
2590          if (result != 0)
2591          {
2592             DBG( "Copy to userspace failure %d\n", result );
2593          }
2594 
2595          return result;
2596 
2597          break;
2598 
2599       default:
2600          return -EBADRQC;
2601    }
2602 }
2603 
2604 /*=========================================================================*/
2605 // Userspace wrappers
2606 /*=========================================================================*/
2607 
2608 /*===========================================================================
2609 METHOD:
2610    UserspaceOpen (Public Method)
2611 
2612 DESCRIPTION:
2613    Userspace open
2614       IOCTL must be called before reads or writes
2615 
2616 PARAMETERS
2617    pInode       [ I ] - kernel file descriptor
2618    pFilp        [ I ] - userspace file descriptor
2619 
2620 RETURN VALUE:
2621    int - 0 for success
2622          Negative errno for failure
2623 ===========================================================================*/
2624 static int UserspaceOpen(
2625    struct inode *         pInode,
2626    struct file *          pFilp )
2627 {
2628    sQMIFilpStorage * pFilpData;
2629 
2630    // Optain device pointer from pInode
2631    sQMIDev * pQMIDev = container_of( pInode->i_cdev,
2632                                      sQMIDev,
2633                                      mCdev );
2634    sGobiUSBNet * pDev = container_of( pQMIDev,
2635                                     sGobiUSBNet,
2636                                     mQMIDev );
2637 
2638    if (pDev->mbMdm9x07)
2639    {
2640       atomic_inc(&pDev->refcount);
2641       if (!pDev->mbQMIReady) {
2642          if (wait_for_completion_interruptible_timeout(&pDev->mQMIReadyCompletion, 15*HZ) <= 0) {
2643             if (atomic_dec_and_test(&pDev->refcount)) {
2644                kfree( pDev );
2645             }
2646             return -ETIMEDOUT;
2647          }
2648       }
2649       atomic_dec(&pDev->refcount);
2650    }
2651 
2652    if (IsDeviceValid( pDev ) == false)
2653    {
2654       DBG( "Invalid device\n" );
2655       return -ENXIO;
2656    }
2657 
2658    // Setup data in pFilp->private_data
2659    pFilp->private_data = kmalloc( sizeof( sQMIFilpStorage ), GFP_KERNEL );
2660    if (pFilp->private_data == NULL)
2661    {
2662       DBG( "Mem error\n" );
2663       return -ENOMEM;
2664    }
2665 
2666    pFilpData = (sQMIFilpStorage *)pFilp->private_data;
2667    pFilpData->mClientID = (u16)-1;
2668    pFilpData->mpDev = pDev;
2669    atomic_inc(&pFilpData->mpDev->refcount);
2670 
2671    return 0;
2672 }
2673 
2674 /*===========================================================================
2675 METHOD:
2676    UserspaceIOCTL (Public Method)
2677 
2678 DESCRIPTION:
2679    Userspace IOCTL functions
2680 
2681 PARAMETERS
2682    pUnusedInode [ I ] - (unused) kernel file descriptor
2683    pFilp        [ I ] - userspace file descriptor
2684    cmd          [ I ] - IOCTL command
2685    arg          [ I ] - IOCTL argument
2686 
2687 RETURN VALUE:
2688    int - 0 for success
2689          Negative errno for failure
2690 ===========================================================================*/
2691 #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,36 ))
2692 static int UserspaceIOCTL(
2693    struct inode *    pUnusedInode,
2694    struct file *     pFilp,
2695    unsigned int      cmd,
2696    unsigned long     arg )
2697 {
2698    // call the internal wrapper function
2699    return (int)UserspaceunlockedIOCTL( pFilp, cmd, arg );
2700 }
2701 #endif
2702 
2703 #ifdef quectel_no_for_each_process
2704 static int UserspaceClose(
2705    struct inode *         pInode,
2706    struct file *          pFilp )
2707 {
2708    sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data;
2709 
2710    if (pFilpData == NULL)
2711    {
2712       DBG( "bad file data\n" );
2713       return -EBADF;
2714    }
2715 
2716    atomic_dec(&pFilpData->mpDev->refcount);
2717 
2718    if (IsDeviceValid( pFilpData->mpDev ) == false)
2719    {
2720       return -ENXIO;
2721    }
2722 
2723    DBG( "0x%04X\n", pFilpData->mClientID );
2724 
2725    // Disable pFilpData so they can't keep sending read or write
2726    //    should this function hang
2727    // Note: memory pointer is still saved in pFilpData to be deleted later
2728    pFilp->private_data = NULL;
2729 
2730    if (pFilpData->mClientID != (u16)-1)
2731    {
2732       if (pFilpData->mpDev->mbDeregisterQMIDevice)
2733          pFilpData->mClientID = (u16)-1; //DeregisterQMIDevice() will release this ClientID
2734       else
2735       ReleaseClientID( pFilpData->mpDev,
2736                        pFilpData->mClientID );
2737    }
2738 
2739    kfree( pFilpData );
2740    return 0;
2741 }
2742 #else
2743 /*===========================================================================
2744 METHOD:
2745    UserspaceClose (Public Method)
2746 
2747 DESCRIPTION:
2748    Userspace close
2749       Release client ID and free memory
2750 
2751 PARAMETERS
2752    pFilp           [ I ] - userspace file descriptor
2753    unusedFileTable [ I ] - (unused) file table
2754 
2755 RETURN VALUE:
2756    int - 0 for success
2757          Negative errno for failure
2758 ===========================================================================*/
2759 #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,14 ))
2760 int UserspaceClose(
2761    struct file *       pFilp,
2762    fl_owner_t          unusedFileTable )
2763 #else
2764 int UserspaceClose( struct file *       pFilp )
2765 #endif
2766 {
2767    sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data;
2768    struct task_struct * pEachTask;
2769    struct fdtable * pFDT;
2770    int count = 0;
2771    int used = 0;
2772    unsigned long flags;
2773 
2774    if (pFilpData == NULL)
2775    {
2776       DBG( "bad file data\n" );
2777       return -EBADF;
2778    }
2779 
2780    // Fallthough.  If f_count == 1 no need to do more checks
2781 #if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,24 ))
2782    if (atomic_read( &pFilp->f_count ) != 1)
2783 #else
2784    if (atomic_long_read( &pFilp->f_count ) != 1)
2785 #endif
2786    {
2787       rcu_read_lock();
2788       for_each_process( pEachTask )
2789       {
2790          task_lock(pEachTask);
2791          if (pEachTask == NULL || pEachTask->files == NULL)
2792          {
2793             // Some tasks may not have files (e.g. Xsession)
2794             task_unlock(pEachTask);
2795             continue;
2796          }
2797          spin_lock_irqsave( &pEachTask->files->file_lock, flags );
2798          task_unlock(pEachTask); //kernel/exit.c:do_exit() -> fs/file.c:exit_files()
2799          pFDT = files_fdtable( pEachTask->files );
2800          for (count = 0; count < pFDT->max_fds; count++)
2801          {
2802             // Before this function was called, this file was removed
2803             // from our task's file table so if we find it in a file
2804             // table then it is being used by another task
2805             if (pFDT->fd[count] == pFilp)
2806             {
2807                used++;
2808                break;
2809             }
2810          }
2811          spin_unlock_irqrestore( &pEachTask->files->file_lock, flags );
2812       }
2813       rcu_read_unlock();
2814 
2815       if (used > 0)
2816       {
2817          DBG( "not closing, as this FD is open by %d other process\n", used );
2818          return 0;
2819       }
2820    }
2821 
2822    if (IsDeviceValid( pFilpData->mpDev ) == false)
2823    {
2824       DBG( "Invalid device! Updating f_ops\n" );
2825       pFilp->f_op = pFilp->f_dentry->d_inode->i_fop;
2826       return -ENXIO;
2827    }
2828 
2829    DBG( "0x%04X\n", pFilpData->mClientID );
2830 
2831    // Disable pFilpData so they can't keep sending read or write
2832    //    should this function hang
2833    // Note: memory pointer is still saved in pFilpData to be deleted later
2834    pFilp->private_data = NULL;
2835 
2836    if (pFilpData->mClientID != (u16)-1)
2837    {
2838       if (pFilpData->mpDev->mbDeregisterQMIDevice)
2839          pFilpData->mClientID = (u16)-1; //DeregisterQMIDevice() will release this ClientID
2840       else
2841       ReleaseClientID( pFilpData->mpDev,
2842                        pFilpData->mClientID );
2843    }
2844    atomic_dec(&pFilpData->mpDev->refcount);
2845 
2846    kfree( pFilpData );
2847    return 0;
2848 }
2849 #endif
2850 
2851 /*===========================================================================
2852 METHOD:
2853    UserspaceRead (Public Method)
2854 
2855 DESCRIPTION:
2856    Userspace read (synchronous)
2857 
2858 PARAMETERS
2859    pFilp           [ I ] - userspace file descriptor
2860    pBuf            [ I ] - read buffer
2861    size            [ I ] - size of read buffer
2862    pUnusedFpos     [ I ] - (unused) file position
2863 
2864 RETURN VALUE:
2865    ssize_t - Number of bytes read for success
2866              Negative errno for failure
2867 ===========================================================================*/
2868 static ssize_t UserspaceRead(
2869    struct file *          pFilp,
2870    char __user *          pBuf,
2871    size_t                 size,
2872    loff_t *               pUnusedFpos )
2873 {
2874    int result;
2875    void * pReadData = NULL;
2876    void * pSmallReadData;
2877    sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data;
2878 
2879    if (pFilpData == NULL)
2880    {
2881       DBG( "Bad file data\n" );
2882       return -EBADF;
2883    }
2884 
2885    if (IsDeviceValid( pFilpData->mpDev ) == false)
2886    {
2887       DBG( "Invalid device! Updating f_ops\n" );
2888       pFilp->f_op = pFilp->f_dentry->d_inode->i_fop;
2889       return -ENXIO;
2890    }
2891 
2892    if (pFilpData->mClientID == (u16)-1)
2893    {
2894       DBG( "Client ID must be set before reading 0x%04X\n",
2895            pFilpData->mClientID );
2896       return -EBADR;
2897    }
2898 
2899    // Perform synchronous read
2900    result = ReadSync( pFilpData->mpDev,
2901                       &pReadData,
2902                       pFilpData->mClientID,
2903                       0 );
2904    if (result <= 0)
2905    {
2906       return result;
2907    }
2908 
2909    // Discard QMUX header
2910    result -= QMUXHeaderSize();
2911    pSmallReadData = pReadData + QMUXHeaderSize();
2912 
2913    if (result > size)
2914    {
2915       DBG( "Read data is too large for amount user has requested\n" );
2916       kfree( pReadData );
2917       return -EOVERFLOW;
2918    }
2919 
2920    DBG(  "pBuf = 0x%p pSmallReadData = 0x%p, result = %d",
2921          pBuf, pSmallReadData, result );
2922 
2923    if (copy_to_user( pBuf, pSmallReadData, result ) != 0)
2924    {
2925       DBG( "Error copying read data to user\n" );
2926       result = -EFAULT;
2927    }
2928 
2929    // Reader is responsible for freeing read buffer
2930    kfree( pReadData );
2931 
2932    return result;
2933 }
2934 
2935 /*===========================================================================
2936 METHOD:
2937    UserspaceWrite (Public Method)
2938 
2939 DESCRIPTION:
2940    Userspace write (synchronous)
2941 
2942 PARAMETERS
2943    pFilp           [ I ] - userspace file descriptor
2944    pBuf            [ I ] - write buffer
2945    size            [ I ] - size of write buffer
2946    pUnusedFpos     [ I ] - (unused) file position
2947 
2948 RETURN VALUE:
2949    ssize_t - Number of bytes read for success
2950              Negative errno for failure
2951 ===========================================================================*/
2952 static ssize_t UserspaceWrite(
2953    struct file *        pFilp,
2954    const char __user *  pBuf,
2955    size_t               size,
2956    loff_t *             pUnusedFpos )
2957 {
2958    int status;
2959    void * pWriteBuffer;
2960    sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data;
2961 
2962    if (pFilpData == NULL)
2963    {
2964       DBG( "Bad file data\n" );
2965       return -EBADF;
2966    }
2967 
2968    if (IsDeviceValid( pFilpData->mpDev ) == false)
2969    {
2970       DBG( "Invalid device! Updating f_ops\n" );
2971       pFilp->f_op = pFilp->f_dentry->d_inode->i_fop;
2972       return -ENXIO;
2973    }
2974 
2975    if (pFilpData->mClientID == (u16)-1)
2976    {
2977       DBG( "Client ID must be set before writing 0x%04X\n",
2978            pFilpData->mClientID );
2979       return -EBADR;
2980    }
2981 
2982    // Copy data from user to kernel space
2983    pWriteBuffer = kmalloc( size + QMUXHeaderSize(), GFP_KERNEL );
2984    if (pWriteBuffer == NULL)
2985    {
2986       return -ENOMEM;
2987    }
2988    status = copy_from_user( pWriteBuffer + QMUXHeaderSize(), pBuf, size );
2989    if (status != 0)
2990    {
2991       DBG( "Unable to copy data from userspace %d\n", status );
2992       kfree( pWriteBuffer );
2993       return status;
2994    }
2995 
2996    status = WriteSync( pFilpData->mpDev,
2997                        pWriteBuffer,
2998                        size + QMUXHeaderSize(),
2999                        pFilpData->mClientID );
3000 
3001    kfree( pWriteBuffer );
3002 
3003    // On success, return requested size, not full QMI reqest size
3004    if (status == size + QMUXHeaderSize())
3005    {
3006       return size;
3007    }
3008    else
3009    {
3010       return status;
3011    }
3012 }
3013 
3014 /*===========================================================================
3015 METHOD:
3016    UserspacePoll (Public Method)
3017 
3018 DESCRIPTION:
3019    Used to determine if read/write operations are possible without blocking
3020 
3021 PARAMETERS
3022    pFilp              [ I ] - userspace file descriptor
3023    pPollTable         [I/O] - Wait object to notify the kernel when data
3024                               is ready
3025 
3026 RETURN VALUE:
3027    unsigned int - bitmask of what operations can be done immediately
3028 ===========================================================================*/
3029 static unsigned int UserspacePoll(
3030    struct file *                  pFilp,
3031    struct poll_table_struct *     pPollTable )
3032 {
3033    sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data;
3034    sClientMemList * pClientMem;
3035    unsigned long flags;
3036 
3037    // Always ready to write
3038    unsigned long status = POLLOUT | POLLWRNORM;
3039 
3040    if (pFilpData == NULL)
3041    {
3042       DBG( "Bad file data\n" );
3043       return POLLERR;
3044    }
3045 
3046    if (IsDeviceValid( pFilpData->mpDev ) == false)
3047    {
3048       DBG( "Invalid device! Updating f_ops\n" );
3049       pFilp->f_op = pFilp->f_dentry->d_inode->i_fop;
3050       return POLLERR;
3051    }
3052 
3053    if (pFilpData->mpDev->mbDeregisterQMIDevice)
3054    {
3055       DBG( "DeregisterQMIDevice ing\n" );
3056       return POLLHUP | POLLERR;
3057    }
3058 
3059    if (pFilpData->mClientID == (u16)-1)
3060    {
3061       DBG( "Client ID must be set before polling 0x%04X\n",
3062            pFilpData->mClientID );
3063       return POLLERR;
3064    }
3065 
3066    // Critical section
3067    spin_lock_irqsave( &pFilpData->mpDev->mQMIDev.mClientMemLock, flags );
3068 
3069    // Get this client's memory location
3070    pClientMem = FindClientMem( pFilpData->mpDev,
3071                                pFilpData->mClientID );
3072    if (pClientMem == NULL)
3073    {
3074       DBG( "Could not find this client's memory 0x%04X\n",
3075            pFilpData->mClientID );
3076 
3077       spin_unlock_irqrestore( &pFilpData->mpDev->mQMIDev.mClientMemLock,
3078                               flags );
3079       return POLLERR;
3080    }
3081 
3082    poll_wait( pFilp, &pClientMem->mWaitQueue, pPollTable );
3083 
3084    if (pClientMem->mpList != NULL)
3085    {
3086       status |= POLLIN | POLLRDNORM;
3087    }
3088 
3089    // End critical section
3090    spin_unlock_irqrestore( &pFilpData->mpDev->mQMIDev.mClientMemLock, flags );
3091 
3092    // Always ready to write
3093    return (status | POLLOUT | POLLWRNORM);
3094 }
3095 
3096 /*=========================================================================*/
3097 // Initializer and destructor
3098 /*=========================================================================*/
3099 static int QMICTLSyncProc(sGobiUSBNet *pDev)
3100 {
3101    void *pWriteBuffer;
3102    void *pReadBuffer;
3103    int result;
3104    u16 writeBufferSize;
3105    u16 readBufferSize;
3106    u8 transactionID;
3107    unsigned long flags;
3108 
3109    if (IsDeviceValid( pDev ) == false)
3110    {
3111       DBG( "Invalid device\n" );
3112       return -EFAULT;
3113    }
3114 
3115    writeBufferSize= QMICTLSyncReqSize();
3116    pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
3117    if (pWriteBuffer == NULL)
3118    {
3119       return -ENOMEM;
3120    }
3121 
3122    transactionID = QMIXactionIDGet(pDev);
3123 
3124    /* send a QMI_CTL_SYNC_REQ (0x0027) */
3125    result = QMICTLSyncReq( pWriteBuffer,
3126                            writeBufferSize,
3127                            transactionID );
3128    if (result < 0)
3129    {
3130       kfree( pWriteBuffer );
3131       return result;
3132    }
3133 
3134    result = WriteSync( pDev,
3135                        pWriteBuffer,
3136                        writeBufferSize,
3137                        QMICTL );
3138 
3139    if (result < 0)
3140    {
3141       kfree( pWriteBuffer );
3142       return result;
3143    }
3144 
3145    // QMI CTL Sync Response
3146    result = ReadSync( pDev,
3147                       &pReadBuffer,
3148                       QMICTL,
3149                       transactionID );
3150    if (result < 0)
3151    {
3152       return result;
3153    }
3154 
3155    result = QMICTLSyncResp( pReadBuffer,
3156                             (u16)result );
3157 
3158    kfree( pReadBuffer );
3159 
3160    if (result < 0) /* need to re-sync */
3161    {
3162       DBG( "sync response error code %d\n", result );
3163       /* start timer and wait for the response */
3164       /* process response */
3165       return result;
3166    }
3167 
3168 #if 1 //free these ununsed qmi response, or when these transactionID re-used, they will be regarded as qmi response of the qmi request that have same transactionID
3169    // Enter critical section
3170    spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
3171 
3172    // Free any unread data
3173    while (PopFromReadMemList( pDev, QMICTL, 0, &pReadBuffer, &readBufferSize) == true) {
3174        kfree( pReadBuffer );
3175    }
3176 
3177    // End critical section
3178    spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3179 #endif
3180 
3181    // Success
3182    return 0;
3183 }
3184 
3185 static int qmi_sync_thread(void *data) {
3186     sGobiUSBNet * pDev = (sGobiUSBNet *)data;
3187     int result = 0;
3188 
3189 #if 1
3190    // Device is not ready for QMI connections right away
3191    //   Wait up to 30 seconds before failing
3192    if (QMIReady( pDev, 30000 ) == false)
3193    {
3194       DBG( "Device unresponsive to QMI\n" );
3195       goto __qmi_sync_finished;
3196    }
3197 
3198    // Initiate QMI CTL Sync Procedure
3199    DBG( "Sending QMI CTL Sync Request\n" );
3200    result = QMICTLSyncProc(pDev);
3201    if (result != 0)
3202    {
3203       DBG( "QMI CTL Sync Procedure Error\n" );
3204       goto __qmi_sync_finished;
3205    }
3206    else
3207    {
3208       DBG( "QMI CTL Sync Procedure Successful\n" );
3209    }
3210 
3211 #if defined(QUECTEL_WWAN_QMAP)
3212 if (pDev->qmap_mode) {
3213    // Setup Data Format
3214    result = QMIWDASetDataFormat (pDev, pDev->qmap_mode, &pDev->qmap_size);
3215    if (result != 0)
3216    {
3217       goto __qmi_sync_finished;
3218    }
3219    pDev->mpNetDev->rx_urb_size = pDev->qmap_size;
3220 }
3221 #endif
3222 
3223    // Setup WDS callback
3224    result = SetupQMIWDSCallback( pDev );
3225    if (result != 0)
3226    {
3227       goto __qmi_sync_finished;
3228    }
3229 
3230    // Fill MEID for device
3231    result = QMIDMSGetMEID( pDev );
3232    if (result != 0)
3233    {
3234       goto __qmi_sync_finished;
3235    }
3236 #endif
3237 
3238 __qmi_sync_finished:
3239    pDev->mbQMIReady = true;
3240    complete_all(&pDev->mQMIReadyCompletion);
3241    pDev->mbQMISyncIng = false;
3242    if (atomic_dec_and_test(&pDev->refcount)) {
3243       kfree( pDev );
3244    }
3245    return result;
3246 }
3247 
3248 /*===========================================================================
3249 METHOD:
3250    RegisterQMIDevice (Public Method)
3251 
3252 DESCRIPTION:
3253    QMI Device initialization function
3254 
3255 PARAMETERS:
3256    pDev     [ I ] - Device specific memory
3257 
3258 RETURN VALUE:
3259    int - 0 for success
3260          Negative errno for failure
3261 ===========================================================================*/
3262 int RegisterQMIDevice( sGobiUSBNet * pDev )
3263 {
3264    int result;
3265    int GobiQMIIndex = 0;
3266    dev_t devno;
3267    char * pDevName;
3268 
3269    if (pDev->mQMIDev.mbCdevIsInitialized == true)
3270    {
3271       // Should never happen, but always better to check
3272       DBG( "device already exists\n" );
3273       return -EEXIST;
3274    }
3275 
3276    pDev->mbQMIValid = true;
3277    pDev->mbDeregisterQMIDevice = false;
3278 
3279    // Set up for QMICTL
3280    //    (does not send QMI message, just sets up memory)
3281    result = GetClientID( pDev, QMICTL );
3282    if (result != 0)
3283    {
3284       pDev->mbQMIValid = false;
3285       return result;
3286    }
3287    atomic_set( &pDev->mQMIDev.mQMICTLTransactionID, 1 );
3288 
3289    // Start Async reading
3290    result = StartRead( pDev );
3291    if (result != 0)
3292    {
3293       pDev->mbQMIValid = false;
3294       return result;
3295    }
3296 
3297    if (pDev->mbMdm9x07)
3298    {
3299       usb_control_msg( pDev->mpNetDev->udev,
3300                             usb_sndctrlpipe( pDev->mpNetDev->udev, 0 ),
3301                              SET_CONTROL_LINE_STATE_REQUEST,
3302                              SET_CONTROL_LINE_STATE_REQUEST_TYPE,
3303                              CONTROL_DTR,
3304                              /* USB interface number to receive control message */
3305                              pDev->mpIntf->cur_altsetting->desc.bInterfaceNumber,
3306                              NULL,
3307                              0,
3308                              100 );
3309    }
3310 
3311     //for EC21&25, must wait about 15 seconds to wait QMI ready. it is too long for driver probe(will block other drivers probe).
3312    if (pDev->mbMdm9x07)
3313    {
3314       struct task_struct *qmi_sync_task;
3315       atomic_inc(&pDev->refcount);
3316       init_completion(&pDev->mQMIReadyCompletion);
3317       pDev->mbQMIReady = false;
3318       pDev->mbQMISyncIng = true;
3319       qmi_sync_task = kthread_run(qmi_sync_thread, (void *)pDev, "qmi_sync/%d", pDev->mpNetDev->udev->devnum);
3320        if (IS_ERR(qmi_sync_task)) {
3321          pDev->mbQMISyncIng = false;
3322          atomic_dec(&pDev->refcount);
3323          DBG( "Create qmi_sync_thread fail\n" );
3324          return PTR_ERR(qmi_sync_task);
3325       }
3326       goto __register_chardev_qccmi;
3327    }
3328 
3329    // Device is not ready for QMI connections right away
3330    //   Wait up to 30 seconds before failing
3331    if (QMIReady( pDev, 30000 ) == false)
3332    {
3333       DBG( "Device unresponsive to QMI\n" );
3334       return -ETIMEDOUT;
3335    }
3336 
3337    // Initiate QMI CTL Sync Procedure
3338    DBG( "Sending QMI CTL Sync Request\n" );
3339    result = QMICTLSyncProc(pDev);
3340    if (result != 0)
3341    {
3342       DBG( "QMI CTL Sync Procedure Error\n" );
3343       return result;
3344    }
3345    else
3346    {
3347       DBG( "QMI CTL Sync Procedure Successful\n" );
3348    }
3349 
3350    // Setup Data Format
3351 #if defined(QUECTEL_WWAN_QMAP)
3352    result = QMIWDASetDataFormat (pDev, pDev->qmap_mode, NULL);
3353 #else
3354    result = QMIWDASetDataFormat (pDev, 0, NULL);
3355 #endif
3356    if (result != 0)
3357    {
3358        return result;
3359    }
3360 
3361    // Setup WDS callback
3362    result = SetupQMIWDSCallback( pDev );
3363    if (result != 0)
3364    {
3365 	  return result;
3366    }
3367 
3368    // Fill MEID for device
3369    result = QMIDMSGetMEID( pDev );
3370    if (result != 0)
3371    {
3372       return result;
3373    }
3374 
3375 __register_chardev_qccmi:
3376    // allocate and fill devno with numbers
3377    result = alloc_chrdev_region( &devno, 0, 1, "qcqmi" );
3378    if (result < 0)
3379    {
3380  	  return result;
3381    }
3382 
3383    // Create cdev
3384    cdev_init( &pDev->mQMIDev.mCdev, &UserspaceQMIFops );
3385    pDev->mQMIDev.mCdev.owner = THIS_MODULE;
3386    pDev->mQMIDev.mCdev.ops = &UserspaceQMIFops;
3387    pDev->mQMIDev.mbCdevIsInitialized = true;
3388 
3389    result = cdev_add( &pDev->mQMIDev.mCdev, devno, 1 );
3390    if (result != 0)
3391    {
3392       DBG( "error adding cdev\n" );
3393       return result;
3394    }
3395 
3396    // Match interface number (usb# or eth#)
3397    if (!!(pDevName = strstr( pDev->mpNetDev->net->name, "eth" ))) {
3398        pDevName += strlen( "eth" );
3399    } else if (!!(pDevName = strstr( pDev->mpNetDev->net->name, "usb" ))) {
3400        pDevName += strlen( "usb" );
3401 #if 1 //openWRT like use ppp# or lte#
3402    } else if (!!(pDevName = strstr( pDev->mpNetDev->net->name, "ppp" ))) {
3403        pDevName += strlen( "ppp" );
3404    } else if (!!(pDevName = strstr( pDev->mpNetDev->net->name, "lte" ))) {
3405        pDevName += strlen( "lte" );
3406 #endif
3407    } else {
3408       DBG( "Bad net name: %s\n", pDev->mpNetDev->net->name );
3409       return -ENXIO;
3410    }
3411    GobiQMIIndex = simple_strtoul( pDevName, NULL, 10 );
3412    if (GobiQMIIndex < 0)
3413    {
3414       DBG( "Bad minor number\n" );
3415       return -ENXIO;
3416    }
3417 
3418    // Always print this output
3419    printk( KERN_INFO "creating qcqmi%d\n",
3420            GobiQMIIndex );
3421 
3422 #if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,27 ))
3423    // kernel 2.6.27 added a new fourth parameter to device_create
3424    //    void * drvdata : the data to be added to the device for callbacks
3425    device_create( pDev->mQMIDev.mpDevClass,
3426                   &pDev->mpIntf->dev,
3427                   devno,
3428                   NULL,
3429                   "qcqmi%d",
3430                   GobiQMIIndex );
3431 #else
3432    device_create( pDev->mQMIDev.mpDevClass,
3433                   &pDev->mpIntf->dev,
3434                   devno,
3435                   "qcqmi%d",
3436                   GobiQMIIndex );
3437 #endif
3438 
3439    pDev->mQMIDev.mDevNum = devno;
3440 
3441    // Success
3442    return 0;
3443 }
3444 
3445 /*===========================================================================
3446 METHOD:
3447    DeregisterQMIDevice (Public Method)
3448 
3449 DESCRIPTION:
3450    QMI Device cleanup function
3451 
3452    NOTE: When this function is run the device is no longer valid
3453 
3454 PARAMETERS:
3455    pDev     [ I ] - Device specific memory
3456 
3457 RETURN VALUE:
3458    None
3459 ===========================================================================*/
3460 void DeregisterQMIDevice( sGobiUSBNet * pDev )
3461 {
3462 #ifndef quectel_no_for_each_process
3463    struct inode * pOpenInode;
3464    struct list_head * pInodeList;
3465    struct task_struct * pEachTask;
3466    struct fdtable * pFDT;
3467    struct file * pFilp;
3468    int count = 0;
3469 #endif
3470    unsigned long flags;
3471    int tries;
3472    int result;
3473 
3474    // Should never happen, but check anyway
3475    if (IsDeviceValid( pDev ) == false)
3476    {
3477       DBG( "wrong device\n" );
3478       return;
3479    }
3480 
3481    pDev->mbDeregisterQMIDevice = true;
3482 
3483    for (tries = 0; tries < 3000; tries += 10) {
3484       if (pDev->mbQMISyncIng == false)
3485          break;
3486       msleep(10);
3487    }
3488 
3489    if (pDev->mbQMISyncIng) {
3490       DBG( "QMI sync ing\n" );
3491    }
3492 
3493    // Release all clients
3494    spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
3495    while (pDev->mQMIDev.mpClientMemList != NULL)
3496    {
3497       u16 mClientID = pDev->mQMIDev.mpClientMemList->mClientID;
3498       if (waitqueue_active(&pDev->mQMIDev.mpClientMemList->mWaitQueue)) {
3499          DBG("WaitQueue 0x%04X\n", mClientID);
3500          wake_up_interruptible_sync( &pDev->mQMIDev.mpClientMemList->mWaitQueue );
3501          spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3502          msleep(10);
3503          spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
3504          continue;
3505       }
3506 
3507       DBG( "release 0x%04X\n", pDev->mQMIDev.mpClientMemList->mClientID );
3508 
3509       spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3510       ReleaseClientID( pDev, mClientID );
3511       // NOTE: pDev->mQMIDev.mpClientMemList will
3512       //       be updated in ReleaseClientID()
3513       spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
3514    }
3515    spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3516 
3517    // Stop all reads
3518    KillRead( pDev );
3519 
3520    pDev->mbQMIValid = false;
3521 
3522    if (pDev->mQMIDev.mbCdevIsInitialized == false)
3523    {
3524       return;
3525    }
3526 
3527 #ifndef quectel_no_for_each_process
3528    // Find each open file handle, and manually close it
3529 
3530    // Generally there will only be only one inode, but more are possible
3531    list_for_each( pInodeList, &pDev->mQMIDev.mCdev.list )
3532    {
3533       // Get the inode
3534       pOpenInode = container_of( pInodeList, struct inode, i_devices );
3535       if (pOpenInode != NULL && (IS_ERR( pOpenInode ) == false))
3536       {
3537          // Look for this inode in each task
3538 
3539          rcu_read_lock();
3540          for_each_process( pEachTask )
3541          {
3542             task_lock(pEachTask);
3543             if (pEachTask == NULL || pEachTask->files == NULL)
3544             {
3545                // Some tasks may not have files (e.g. Xsession)
3546                task_unlock(pEachTask);
3547                continue;
3548             }
3549             // For each file this task has open, check if it's referencing
3550             // our inode.
3551             spin_lock_irqsave( &pEachTask->files->file_lock, flags );
3552             task_unlock(pEachTask);  //kernel/exit.c:do_exit() -> fs/file.c:exit_files()
3553             pFDT = files_fdtable( pEachTask->files );
3554             for (count = 0; count < pFDT->max_fds; count++)
3555             {
3556                pFilp = pFDT->fd[count];
3557                if (pFilp != NULL &&  pFilp->f_dentry != NULL)
3558                {
3559                   if (pFilp->f_dentry->d_inode == pOpenInode)
3560                   {
3561                      // Close this file handle
3562                      rcu_assign_pointer( pFDT->fd[count], NULL );
3563                      spin_unlock_irqrestore( &pEachTask->files->file_lock, flags );
3564 
3565                      DBG( "forcing close of open file handle\n" );
3566                      filp_close( pFilp, pEachTask->files );
3567 
3568                      spin_lock_irqsave( &pEachTask->files->file_lock, flags );
3569                   }
3570                }
3571             }
3572             spin_unlock_irqrestore( &pEachTask->files->file_lock, flags );
3573          }
3574          rcu_read_unlock();
3575       }
3576    }
3577 #endif
3578 
3579 if (pDev->mpNetDev->udev->state) {
3580    // Send SetControlLineState request (USB_CDC)
3581    result = usb_control_msg( pDev->mpNetDev->udev,
3582                              usb_sndctrlpipe( pDev->mpNetDev->udev, 0 ),
3583                              SET_CONTROL_LINE_STATE_REQUEST,
3584                              SET_CONTROL_LINE_STATE_REQUEST_TYPE,
3585                              0, // DTR not present
3586                              /* USB interface number to receive control message */
3587                              pDev->mpIntf->cur_altsetting->desc.bInterfaceNumber,
3588                              NULL,
3589                              0,
3590                              100 );
3591    if (result < 0)
3592    {
3593       DBG( "Bad SetControlLineState status %d\n", result );
3594    }
3595 }
3596 
3597    // Remove device (so no more calls can be made by users)
3598    if (IS_ERR( pDev->mQMIDev.mpDevClass ) == false)
3599    {
3600       device_destroy( pDev->mQMIDev.mpDevClass,
3601                       pDev->mQMIDev.mDevNum );
3602    }
3603 
3604    // Hold onto cdev memory location until everyone is through using it.
3605    // Timeout after 30 seconds (10 ms interval).  Timeout should never happen,
3606    // but exists to prevent an infinate loop just in case.
3607    for (tries = 0; tries < 30 * 100; tries++)
3608    {
3609 #if (LINUX_VERSION_CODE < KERNEL_VERSION( 4,11,0 ))
3610       int ref = atomic_read( &pDev->mQMIDev.mCdev.kobj.kref.refcount );
3611 #else
3612       int ref = kref_read( &pDev->mQMIDev.mCdev.kobj.kref );
3613 #endif
3614       if (ref > 1)
3615       {
3616          DBG( "cdev in use by %d tasks\n", ref - 1 );
3617          if (tries > 10)
3618             INFO( "cdev in use by %d tasks\n", ref - 1 );
3619          msleep( 10 );
3620       }
3621       else
3622       {
3623          break;
3624       }
3625    }
3626 
3627    cdev_del( &pDev->mQMIDev.mCdev );
3628 
3629    unregister_chrdev_region( pDev->mQMIDev.mDevNum, 1 );
3630 
3631    return;
3632 }
3633 
3634 /*=========================================================================*/
3635 // Driver level client management
3636 /*=========================================================================*/
3637 
3638 /*===========================================================================
3639 METHOD:
3640    QMIReady (Public Method)
3641 
3642 DESCRIPTION:
3643    Send QMI CTL GET VERSION INFO REQ and SET DATA FORMAT REQ
3644    Wait for response or timeout
3645 
3646 PARAMETERS:
3647    pDev     [ I ] - Device specific memory
3648    timeout  [ I ] - Milliseconds to wait for response
3649 
3650 RETURN VALUE:
3651    bool
3652 ===========================================================================*/
3653 static bool QMIReady(
3654    sGobiUSBNet *    pDev,
3655    u16                timeout )
3656 {
3657    int result;
3658    void * pWriteBuffer;
3659    u16 writeBufferSize;
3660    void * pReadBuffer;
3661    u16 readBufferSize;
3662    u16 curTime;
3663    unsigned long flags;
3664    u8 transactionID;
3665    u16 interval = 2000;
3666 
3667    if (IsDeviceValid( pDev ) == false)
3668    {
3669       DBG( "Invalid device\n" );
3670       return false;
3671    }
3672 
3673    writeBufferSize = QMICTLReadyReqSize();
3674    pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
3675    if (pWriteBuffer == NULL)
3676    {
3677       return false;
3678    }
3679 
3680    // An implimentation of down_timeout has not been agreed on,
3681    //    so it's been added and removed from the kernel several times.
3682    //    We're just going to ignore it and poll the semaphore.
3683 
3684    // Send a write every 1000 ms and see if we get a response
3685    for (curTime = 0; curTime < timeout; curTime += interval)
3686    {
3687       // Start read
3688       struct QuecSem *readSem = kmalloc(sizeof(struct QuecSem ), GFP_KERNEL);
3689       readSem->magic = QUEC_SEM_MAGIC;
3690       sema_init( &readSem->readSem, 0 );
3691 
3692       transactionID = QMIXactionIDGet( pDev );
3693 
3694       result = ReadAsync( pDev, QMICTL, transactionID, UpSem, readSem );
3695       if (result != 0)
3696       {
3697          kfree( pWriteBuffer );
3698          return false;
3699       }
3700 
3701       // Fill buffer
3702       result = QMICTLReadyReq( pWriteBuffer,
3703                                writeBufferSize,
3704                                transactionID );
3705       if (result < 0)
3706       {
3707          kfree( pWriteBuffer );
3708          return false;
3709       }
3710 
3711       // Disregard status.  On errors, just try again
3712       result = WriteSync( pDev,
3713                  pWriteBuffer,
3714                  writeBufferSize,
3715                  QMICTL );
3716 
3717       if (result < 0) //maybe caused by usb disconnect
3718       {
3719          kfree( pWriteBuffer );
3720          return false;
3721       }
3722 
3723 #if 1
3724       if (down_timeout( &readSem->readSem, msecs_to_jiffies(interval) ) == 0)
3725 #else
3726       msleep( interval );
3727       if (down_trylock( &readSem->readSem ) == 0)
3728 #endif
3729       {
3730          kfree(readSem);
3731          // Enter critical section
3732          spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
3733 
3734          // Pop the read data
3735          if (PopFromReadMemList( pDev,
3736                                  QMICTL,
3737                                  transactionID,
3738                                  &pReadBuffer,
3739                                  &readBufferSize ) == true)
3740          {
3741             // Success
3742 
3743             // End critical section
3744             spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3745 
3746             // We don't care about the result
3747             kfree( pReadBuffer );
3748 
3749             break;
3750          }
3751          else
3752          {
3753             // Read mismatch/failure, unlock and continue
3754             spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3755          }
3756       }
3757       else
3758       {
3759          readSem->magic = 0;
3760          // Enter critical section
3761          spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
3762 
3763          // Timeout, remove the async read
3764          NotifyAndPopNotifyList( pDev, QMICTL, transactionID );
3765 
3766          // End critical section
3767          spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3768       }
3769 
3770       if (pDev->mbDeregisterQMIDevice)
3771       {
3772          kfree( pWriteBuffer );
3773          return false;
3774       }
3775    }
3776 
3777    kfree( pWriteBuffer );
3778 
3779    // Did we time out?
3780    if (curTime >= timeout)
3781    {
3782       return false;
3783    }
3784 
3785    DBG( "QMI Ready after %u milliseconds\n", curTime );
3786 
3787    // Success
3788    return true;
3789 }
3790 
3791 /*===========================================================================
3792 METHOD:
3793    QMIWDSCallback (Public Method)
3794 
3795 DESCRIPTION:
3796    QMI WDS callback function
3797    Update net stats or link state
3798 
3799 PARAMETERS:
3800    pDev     [ I ] - Device specific memory
3801    clientID [ I ] - Client ID
3802    pData    [ I ] - Callback data (unused)
3803 
3804 RETURN VALUE:
3805    None
3806 ===========================================================================*/
3807 static void QMIWDSCallback(
3808    sGobiUSBNet *    pDev,
3809    u16                clientID,
3810    void *             pData )
3811 {
3812    bool bRet;
3813    int result;
3814    void * pReadBuffer;
3815    u16 readBufferSize;
3816 
3817 #if 0
3818 #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,31 ))
3819    struct net_device_stats * pStats = &(pDev->mpNetDev->stats);
3820 #else
3821    struct net_device_stats * pStats = &(pDev->mpNetDev->net->stats);
3822 #endif
3823 #endif
3824 
3825    u32 TXOk = (u32)-1;
3826    u32 RXOk = (u32)-1;
3827    u32 TXErr = (u32)-1;
3828    u32 RXErr = (u32)-1;
3829    u32 TXOfl = (u32)-1;
3830    u32 RXOfl = (u32)-1;
3831    u64 TXBytesOk = (u64)-1;
3832    u64 RXBytesOk = (u64)-1;
3833    bool bLinkState;
3834    bool bReconfigure;
3835    unsigned long flags;
3836 
3837    if (IsDeviceValid( pDev ) == false)
3838    {
3839       DBG( "Invalid device\n" );
3840       return;
3841    }
3842 
3843    // Critical section
3844    spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
3845 
3846    bRet = PopFromReadMemList( pDev,
3847                               clientID,
3848                               0,
3849                               &pReadBuffer,
3850                               &readBufferSize );
3851 
3852    // End critical section
3853    spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3854 
3855    if (bRet == false)
3856    {
3857       DBG( "WDS callback failed to get data\n" );
3858       return;
3859    }
3860 
3861    // Default values
3862    bLinkState = ! GobiTestDownReason( pDev, NO_NDIS_CONNECTION );
3863    bReconfigure = false;
3864 
3865    result = QMIWDSEventResp( pReadBuffer,
3866                              readBufferSize,
3867                              &TXOk,
3868                              &RXOk,
3869                              &TXErr,
3870                              &RXErr,
3871                              &TXOfl,
3872                              &RXOfl,
3873                              &TXBytesOk,
3874                              &RXBytesOk,
3875                              &bLinkState,
3876                              &bReconfigure );
3877    if (result < 0)
3878    {
3879       DBG( "bad WDS packet\n" );
3880    }
3881    else
3882    {
3883 #if 0 //usbbet.c will do this job
3884       // Fill in new values, ignore max values
3885       if (TXOfl != (u32)-1)
3886       {
3887          pStats->tx_fifo_errors = TXOfl;
3888       }
3889 
3890       if (RXOfl != (u32)-1)
3891       {
3892          pStats->rx_fifo_errors = RXOfl;
3893       }
3894 
3895       if (TXErr != (u32)-1)
3896       {
3897          pStats->tx_errors = TXErr;
3898       }
3899 
3900       if (RXErr != (u32)-1)
3901       {
3902          pStats->rx_errors = RXErr;
3903       }
3904 
3905       if (TXOk != (u32)-1)
3906       {
3907          pStats->tx_packets = TXOk + pStats->tx_errors;
3908       }
3909 
3910       if (RXOk != (u32)-1)
3911       {
3912          pStats->rx_packets = RXOk + pStats->rx_errors;
3913       }
3914 
3915       if (TXBytesOk != (u64)-1)
3916       {
3917          pStats->tx_bytes = TXBytesOk;
3918       }
3919 
3920       if (RXBytesOk != (u64)-1)
3921       {
3922          pStats->rx_bytes = RXBytesOk;
3923       }
3924 #endif
3925 
3926       if (bReconfigure == true)
3927       {
3928          DBG( "Net device link reset\n" );
3929          GobiSetDownReason( pDev, NO_NDIS_CONNECTION );
3930          GobiClearDownReason( pDev, NO_NDIS_CONNECTION );
3931       }
3932       else
3933       {
3934          if (bLinkState == true)
3935          {
3936             if (GobiTestDownReason( pDev, NO_NDIS_CONNECTION )) {
3937                 DBG( "Net device link is connected\n" );
3938                 GobiClearDownReason( pDev, NO_NDIS_CONNECTION );
3939             }
3940          }
3941          else
3942          {
3943             if (!GobiTestDownReason( pDev, NO_NDIS_CONNECTION )) {
3944                 DBG( "Net device link is disconnected\n" );
3945                 GobiSetDownReason( pDev, NO_NDIS_CONNECTION );
3946             }
3947          }
3948       }
3949    }
3950 
3951    kfree( pReadBuffer );
3952 
3953    // Setup next read
3954    result = ReadAsync( pDev,
3955                        clientID,
3956                        0,
3957                        QMIWDSCallback,
3958                        pData );
3959    if (result != 0)
3960    {
3961       DBG( "unable to setup next async read\n" );
3962    }
3963 
3964    return;
3965 }
3966 
3967 /*===========================================================================
3968 METHOD:
3969    SetupQMIWDSCallback (Public Method)
3970 
3971 DESCRIPTION:
3972    Request client and fire off reqests and start async read for
3973    QMI WDS callback
3974 
3975 PARAMETERS:
3976    pDev     [ I ] - Device specific memory
3977 
3978 RETURN VALUE:
3979    int - 0 for success
3980          Negative errno for failure
3981 ===========================================================================*/
3982 static int SetupQMIWDSCallback( sGobiUSBNet * pDev )
3983 {
3984    int result;
3985    void * pWriteBuffer;
3986    u16 writeBufferSize;
3987    u16 WDSClientID;
3988 
3989    if (IsDeviceValid( pDev ) == false)
3990    {
3991       DBG( "Invalid device\n" );
3992       return -EFAULT;
3993    }
3994 
3995    result = GetClientID( pDev, QMIWDS );
3996    if (result < 0)
3997    {
3998       return result;
3999    }
4000    WDSClientID = result;
4001 
4002 #if 0 // add for "AT$QCRMCALL=1,1", be careful: donot enable these codes if use quectel-CM, or cannot obtain IP by udhcpc
4003     if (pDev->mbMdm9x07)
4004     {
4005        void * pReadBuffer;
4006        u16 readBufferSize;
4007 
4008         writeBufferSize = QMIWDSSetQMUXBindMuxDataPortSize();
4009         pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
4010         if (pWriteBuffer == NULL)
4011         {
4012             return -ENOMEM;
4013         }
4014 
4015         result = QMIWDSSetQMUXBindMuxDataPortReq( pWriteBuffer,
4016                                          writeBufferSize,
4017                                          0x81,
4018                                          3 );
4019         if (result < 0)
4020         {
4021             kfree( pWriteBuffer );
4022             return result;
4023         }
4024 
4025        result = WriteSync( pDev,
4026                            pWriteBuffer,
4027                            writeBufferSize,
4028                            WDSClientID );
4029         kfree( pWriteBuffer );
4030 
4031         if (result < 0)
4032         {
4033             return result;
4034         }
4035 
4036         result = ReadSync( pDev,
4037                           &pReadBuffer,
4038                           WDSClientID,
4039                           3 );
4040         if (result < 0)
4041         {
4042             return result;
4043         }
4044         readBufferSize = result;
4045 
4046         kfree( pReadBuffer );
4047    }
4048 #endif
4049 
4050    // QMI WDS Set Event Report
4051    writeBufferSize = QMIWDSSetEventReportReqSize();
4052    pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
4053    if (pWriteBuffer == NULL)
4054    {
4055       return -ENOMEM;
4056    }
4057 
4058    result = QMIWDSSetEventReportReq( pWriteBuffer,
4059                                      writeBufferSize,
4060                                      1 );
4061    if (result < 0)
4062    {
4063       kfree( pWriteBuffer );
4064       return result;
4065    }
4066 
4067    result = WriteSync( pDev,
4068                        pWriteBuffer,
4069                        writeBufferSize,
4070                        WDSClientID );
4071    kfree( pWriteBuffer );
4072 
4073    if (result < 0)
4074    {
4075       return result;
4076    }
4077 
4078    // QMI WDS Get PKG SRVC Status
4079    writeBufferSize = QMIWDSGetPKGSRVCStatusReqSize();
4080    pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
4081    if (pWriteBuffer == NULL)
4082    {
4083       return -ENOMEM;
4084    }
4085 
4086    result = QMIWDSGetPKGSRVCStatusReq( pWriteBuffer,
4087                                        writeBufferSize,
4088                                        2 );
4089    if (result < 0)
4090    {
4091       kfree( pWriteBuffer );
4092       return result;
4093    }
4094 
4095    result = WriteSync( pDev,
4096                        pWriteBuffer,
4097                        writeBufferSize,
4098                        WDSClientID );
4099    kfree( pWriteBuffer );
4100 
4101    if (result < 0)
4102    {
4103       return result;
4104    }
4105 
4106    // Setup asnyc read callback
4107    result = ReadAsync( pDev,
4108                        WDSClientID,
4109                        0,
4110                        QMIWDSCallback,
4111                        NULL );
4112    if (result != 0)
4113    {
4114       DBG( "unable to setup async read\n" );
4115       return result;
4116    }
4117 
4118    // Send SetControlLineState request (USB_CDC)
4119    //   Required for Autoconnect
4120    result = usb_control_msg( pDev->mpNetDev->udev,
4121                              usb_sndctrlpipe( pDev->mpNetDev->udev, 0 ),
4122                              SET_CONTROL_LINE_STATE_REQUEST,
4123                              SET_CONTROL_LINE_STATE_REQUEST_TYPE,
4124                              CONTROL_DTR,
4125                              /* USB interface number to receive control message */
4126                              pDev->mpIntf->cur_altsetting->desc.bInterfaceNumber,
4127                              NULL,
4128                              0,
4129                              100 );
4130    if (result < 0)
4131    {
4132       DBG( "Bad SetControlLineState status %d\n", result );
4133       return result;
4134    }
4135 
4136    return 0;
4137 }
4138 
4139 /*===========================================================================
4140 METHOD:
4141    QMIDMSGetMEID (Public Method)
4142 
4143 DESCRIPTION:
4144    Register DMS client
4145    send MEID req and parse response
4146    Release DMS client
4147 
4148 PARAMETERS:
4149    pDev     [ I ] - Device specific memory
4150 
4151 RETURN VALUE:
4152    None
4153 ===========================================================================*/
4154 static int QMIDMSGetMEID( sGobiUSBNet * pDev )
4155 {
4156    int result;
4157    void * pWriteBuffer;
4158    u16 writeBufferSize;
4159    void * pReadBuffer;
4160    u16 readBufferSize;
4161    u16 DMSClientID;
4162 
4163    if (IsDeviceValid( pDev ) == false)
4164    {
4165       DBG( "Invalid device\n" );
4166       return -EFAULT;
4167    }
4168 
4169    result = GetClientID( pDev, QMIDMS );
4170    if (result < 0)
4171    {
4172       return result;
4173    }
4174    DMSClientID = result;
4175 
4176    // QMI DMS Get Serial numbers Req
4177    writeBufferSize = QMIDMSGetMEIDReqSize();
4178    pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
4179    if (pWriteBuffer == NULL)
4180    {
4181       return -ENOMEM;
4182    }
4183 
4184    result = QMIDMSGetMEIDReq( pWriteBuffer,
4185                               writeBufferSize,
4186                               1 );
4187    if (result < 0)
4188    {
4189       kfree( pWriteBuffer );
4190       return result;
4191    }
4192 
4193    result = WriteSync( pDev,
4194                        pWriteBuffer,
4195                        writeBufferSize,
4196                        DMSClientID );
4197    kfree( pWriteBuffer );
4198 
4199    if (result < 0)
4200    {
4201       return result;
4202    }
4203 
4204    // QMI DMS Get Serial numbers Resp
4205    result = ReadSync( pDev,
4206                       &pReadBuffer,
4207                       DMSClientID,
4208                       1 );
4209    if (result < 0)
4210    {
4211       return result;
4212    }
4213    readBufferSize = result;
4214 
4215    result = QMIDMSGetMEIDResp( pReadBuffer,
4216                                readBufferSize,
4217                                &pDev->mMEID[0],
4218                                14 );
4219    kfree( pReadBuffer );
4220 
4221    if (result < 0)
4222    {
4223       DBG( "bad get MEID resp\n" );
4224 
4225       // Non fatal error, device did not return any MEID
4226       //    Fill with 0's
4227       memset( &pDev->mMEID[0], '0', 14 );
4228    }
4229 
4230    ReleaseClientID( pDev, DMSClientID );
4231 
4232    // Success
4233    return 0;
4234 }
4235 
4236 /*===========================================================================
4237 METHOD:
4238    QMIWDASetDataFormat (Public Method)
4239 
4240 DESCRIPTION:
4241    Register WDA client
4242    send Data format request and parse response
4243    Release WDA client
4244 
4245 PARAMETERS:
4246    pDev     [ I ] - Device specific memory
4247 
4248 RETURN VALUE:
4249    None
4250 ===========================================================================*/
4251 static int QMIWDASetDataFormat( sGobiUSBNet * pDev, int qmap_mode, int *rx_urb_size )
4252 {
4253    int result;
4254    void * pWriteBuffer;
4255    u16 writeBufferSize;
4256    void * pReadBuffer;
4257    u16 readBufferSize;
4258    u16 WDAClientID;
4259 
4260    DBG("\n");
4261 
4262    if (IsDeviceValid( pDev ) == false)
4263    {
4264       DBG( "Invalid device\n" );
4265       return -EFAULT;
4266    }
4267 
4268    result = GetClientID( pDev, QMIWDA );
4269    if (result < 0)
4270    {
4271       return result;
4272    }
4273    WDAClientID = result;
4274 
4275    // QMI WDA Set Data Format Request
4276    writeBufferSize = QMIWDASetDataFormatReqSize(qmap_mode);
4277    pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
4278    if (pWriteBuffer == NULL)
4279    {
4280       return -ENOMEM;
4281    }
4282 
4283    result = QMIWDASetDataFormatReq( pWriteBuffer,
4284                               writeBufferSize, pDev->mbRawIPMode,
4285                               qmap_mode ? pDev->qmap_version : 0, (31*1024),
4286                               1 );
4287 
4288    if (result < 0)
4289    {
4290       kfree( pWriteBuffer );
4291       return result;
4292    }
4293 
4294    result = WriteSync( pDev,
4295                        pWriteBuffer,
4296                        writeBufferSize,
4297                        WDAClientID );
4298    kfree( pWriteBuffer );
4299 
4300    if (result < 0)
4301    {
4302       return result;
4303    }
4304 
4305    // QMI DMS Get Serial numbers Resp
4306    result = ReadSync( pDev,
4307                       &pReadBuffer,
4308                       WDAClientID,
4309                       1 );
4310    if (result < 0)
4311    {
4312       return result;
4313    }
4314    readBufferSize = result;
4315 
4316 if (qmap_mode && rx_urb_size) {
4317    int qmap_version = 0, rx_size = 0, tx_size = 0;
4318    result = QMIWDASetDataFormatResp( pReadBuffer,
4319                                      readBufferSize, pDev->mbRawIPMode, &qmap_version, &rx_size, &tx_size, &pDev->qmap_settings);
4320     INFO( "qmap settings qmap_version=%d, rx_size=%d, tx_size=%d\n",
4321         le32_to_cpu(qmap_version), le32_to_cpu(rx_size), le32_to_cpu(tx_size));
4322 
4323     if (le32_to_cpu(qmap_version)) {
4324 #if defined(QUECTEL_UL_DATA_AGG)
4325         struct ul_agg_ctx *ctx = &pDev->agg_ctx;
4326 
4327         if (le32_to_cpu(pDev->qmap_settings.ul_data_aggregation_max_datagrams) > 1) {
4328             ctx->ul_data_aggregation_max_size = le32_to_cpu(pDev->qmap_settings.ul_data_aggregation_max_size);
4329             ctx->ul_data_aggregation_max_datagrams = le32_to_cpu(pDev->qmap_settings.ul_data_aggregation_max_datagrams);
4330             ctx->dl_minimum_padding = le32_to_cpu(pDev->qmap_settings.dl_minimum_padding);
4331         }
4332         INFO( "qmap settings ul_data_aggregation_max_size=%d, ul_data_aggregation_max_datagrams=%d\n",
4333                 ctx->ul_data_aggregation_max_size, ctx->ul_data_aggregation_max_datagrams);
4334 	if (ctx->ul_data_aggregation_max_datagrams > 11)
4335 		ctx->ul_data_aggregation_max_datagrams = 11;
4336 #endif
4337         *rx_urb_size = le32_to_cpu(rx_size);
4338     } else {
4339         *rx_urb_size = 0;
4340         result = -EFAULT;
4341     }
4342 } else {
4343    int qmap_enabled = 0, rx_size = 0, tx_size = 0;
4344    result = QMIWDASetDataFormatResp( pReadBuffer,
4345                                      readBufferSize, pDev->mbRawIPMode, &qmap_enabled, &rx_size, &tx_size, NULL);
4346 }
4347 
4348    kfree( pReadBuffer );
4349 
4350    if (result < 0)
4351    {
4352       DBG( "Data Format Cannot be set\n" );
4353    }
4354 
4355    ReleaseClientID( pDev, WDAClientID );
4356 
4357    // Success
4358     return 0;
4359 }
4360 
4361 int QuecQMIWDASetDataFormat( sGobiUSBNet * pDev, int qmap_mode, int *rx_urb_size ) {
4362 	return QMIWDASetDataFormat(pDev, qmap_mode, rx_urb_size);
4363 }
4364