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