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