Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
[pandora-kernel.git] / drivers / staging / bcm / InterfaceMisc.c
1 #include "headers.h"
2
3 #ifndef BCM_SHM_INTERFACE
4
5 PS_INTERFACE_ADAPTER
6 InterfaceAdapterGet(PMINI_ADAPTER psAdapter)
7 {
8         if(psAdapter == NULL)
9         {
10                 return NULL;
11         }
12         return (PS_INTERFACE_ADAPTER)(psAdapter->pvInterfaceAdapter);
13 }
14
15 INT
16 InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
17             UINT addr,
18             PVOID buff,
19             INT len)
20 {
21         int retval = 0;
22         USHORT usRetries = 0 ;
23         if(psIntfAdapter == NULL )
24         {
25                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Interface Adapter is NULL");
26                 return -EINVAL ;
27         }
28
29         if(psIntfAdapter->psAdapter->device_removed == TRUE)
30         {
31                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Device got removed");
32                 return -ENODEV;
33         }
34
35         if((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB))
36         {
37                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL,"Currently Xaction is not allowed on the bus");
38                 return -EACCES;
39         }
40
41         if(psIntfAdapter->bSuspended ==TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE)
42         {
43                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL,"Bus is in suspended states hence RDM not allowed..");
44                 return -EACCES;
45         }
46         psIntfAdapter->psAdapter->DeviceAccess = TRUE ;
47         do {
48                 retval = usb_control_msg(psIntfAdapter->udev,
49                                 usb_rcvctrlpipe(psIntfAdapter->udev,0),
50                     0x02,
51                     0xC2,
52                     (addr & 0xFFFF),
53                     ((addr >> 16) & 0xFFFF),
54                                 buff,
55                     len,
56                     5000);
57
58                 usRetries++ ;
59                 if(-ENODEV == retval)
60                 {
61                         psIntfAdapter->psAdapter->device_removed =TRUE;
62                         break;
63                 }
64
65         }while((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES ) );
66
67         if(retval < 0)
68         {
69                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", retval,usRetries);
70                         psIntfAdapter->psAdapter->DeviceAccess = FALSE ;
71                         return retval;
72         }
73         else
74         {
75                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", retval);
76                         psIntfAdapter->psAdapter->DeviceAccess = FALSE ;
77                         return STATUS_SUCCESS;
78         }
79 }
80
81 INT
82 InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,
83             UINT addr,
84             PVOID buff,
85             INT len)
86 {
87         int retval = 0;
88         USHORT usRetries = 0 ;
89
90         if(psIntfAdapter == NULL )
91         {
92                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Interface Adapter  is NULL");
93                 return -EINVAL;
94         }
95         if(psIntfAdapter->psAdapter->device_removed == TRUE)
96         {
97
98                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Device got removed");
99                 return -ENODEV;
100         }
101
102         if((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB))
103         {
104                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL,"Currently Xaction is not allowed on the bus...");
105                 return EACCES;
106         }
107
108         if(psIntfAdapter->bSuspended ==TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE)
109         {
110                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL,"Bus is in suspended states hence RDM not allowed..");
111                 return -EACCES;
112         }
113         psIntfAdapter->psAdapter->DeviceAccess = TRUE ;
114         do{
115                 retval = usb_control_msg(psIntfAdapter->udev,
116                                 usb_sndctrlpipe(psIntfAdapter->udev,0),
117                     0x01,
118                     0x42,
119                     (addr & 0xFFFF),
120                     ((addr >> 16) & 0xFFFF),
121                                 buff,
122                     len,
123                     5000);
124
125                 usRetries++ ;
126                 if(-ENODEV == retval)
127                 {
128                         psIntfAdapter->psAdapter->device_removed = TRUE ;
129                         break;
130                 }
131
132         }while((retval < 0) && ( usRetries < MAX_RDM_WRM_RETIRES));
133
134         if(retval < 0)
135         {
136                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d, retires :%d", retval, usRetries);
137                 psIntfAdapter->psAdapter->DeviceAccess = FALSE ;
138                 return retval;
139         }
140         else
141         {
142                 psIntfAdapter->psAdapter->DeviceAccess = FALSE ;
143                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM sent %d", retval);
144                 return STATUS_SUCCESS;
145
146         }
147
148 }
149
150 INT
151 BcmRDM(PVOID arg,
152                         UINT addr,
153                         PVOID buff,
154                         INT len)
155 {
156         return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
157 }
158
159 INT
160 BcmWRM(PVOID arg,
161                         UINT addr,
162                         PVOID buff,
163                         INT len)
164 {
165         return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
166 }
167
168
169
170 INT Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter)
171 {
172         PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter);
173         INT status = STATUS_SUCCESS ;
174
175         /*
176                  usb_clear_halt - tells device to clear endpoint halt/stall condition
177                  @dev: device whose endpoint is halted
178                  @pipe: endpoint "pipe" being cleared
179                  @ Context: !in_interrupt ()
180
181                 usb_clear_halt is the synchrnous call and returns 0 on success else returns with error code.
182                 This is used to clear halt conditions for bulk and interrupt endpoints only.
183                  Control and isochronous endpoints never halts.
184
185                 Any URBs  queued for such an endpoint should normally be unlinked by the driver
186                 before clearing the halt condition.
187
188         */
189
190         //Killing all the submitted urbs to different end points.
191         Bcm_kill_all_URBs(psIntfAdapter);
192
193
194         //clear the halted/stalled state for every end point
195         status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sIntrIn.int_in_pipe);
196         if(status != STATUS_SUCCESS)
197                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Interrupt IN end point. :%d ", status);
198
199         status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sBulkIn.bulk_in_pipe);
200         if(status != STATUS_SUCCESS)
201                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk IN end point. :%d ", status);
202
203         status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sBulkOut.bulk_out_pipe);
204         if(status != STATUS_SUCCESS)
205                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk OUT end point. :%d ", status);
206
207         return status ;
208 }
209
210
211 VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
212 {
213         struct urb *tempUrb = NULL;
214         UINT i;
215
216         /**
217           *     usb_kill_urb - cancel a transfer request and wait for it to finish
218           *     @urb: pointer to URB describing a previously submitted request,
219           *       returns nothing as it is void returned API.
220           *
221           *      This routine cancels an in-progress request. It is guaranteed that
222           *     upon return all completion handlers will have finished and the URB
223           *     will be totally idle and available for reuse
224
225           *     This routine may not be used in an interrupt context (such as a bottom
226           *      half or a completion handler), or when holding a spinlock, or in other
227           *      situations where the caller can't schedule().
228           *
229         **/
230
231         /* Cancel submitted Interrupt-URB's */
232         if(psIntfAdapter->psInterruptUrb != NULL)
233         {
234                 if(psIntfAdapter->psInterruptUrb->status == -EINPROGRESS)
235                                  usb_kill_urb(psIntfAdapter->psInterruptUrb);
236         }
237
238         /* Cancel All submitted TX URB's */
239         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cancelling All Submitted TX Urbs \n");
240
241     for(i = 0; i < MAXIMUM_USB_TCB; i++)
242         {
243                 tempUrb = psIntfAdapter->asUsbTcb[i].urb;
244                 if(tempUrb)
245                 {
246                         if(tempUrb->status == -EINPROGRESS)
247                                 usb_kill_urb(tempUrb);
248                 }
249         }
250
251
252     BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cancelling All submitted Rx Urbs \n");
253
254         for(i = 0; i < MAXIMUM_USB_RCB; i++)
255         {
256                 tempUrb = psIntfAdapter->asUsbRcb[i].urb;
257                 if(tempUrb)
258                 {
259                         if(tempUrb->status == -EINPROGRESS)
260                                         usb_kill_urb(tempUrb);
261                 }
262         }
263
264
265         atomic_set(&psIntfAdapter->uNumTcbUsed, 0);
266         atomic_set(&psIntfAdapter->uCurrTcb, 0);
267
268         atomic_set(&psIntfAdapter->uNumRcbUsed, 0);
269         atomic_set(&psIntfAdapter->uCurrRcb, 0);
270
271         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "TCB: used- %d cur-%d\n", atomic_read(&psIntfAdapter->uNumTcbUsed), atomic_read(&psIntfAdapter->uCurrTcb));
272         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "RCB: used- %d cur-%d\n", atomic_read(&psIntfAdapter->uNumRcbUsed), atomic_read(&psIntfAdapter->uCurrRcb));
273
274 }
275
276 VOID putUsbSuspend(struct work_struct *work)
277 {
278         PS_INTERFACE_ADAPTER psIntfAdapter = NULL ;
279         struct usb_interface *intf = NULL ;
280         psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER,usbSuspendWork);
281         intf=psIntfAdapter->interface ;
282
283         if(psIntfAdapter->bSuspended == FALSE)
284                 usb_autopm_put_interface(intf);
285         else
286                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Interface Resumed Completely\n");
287
288 }
289
290 #endif