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