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