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