blob: 61f878b4f56c1de900d55941e42c6a63bce3e3bd [file] [log] [blame]
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001#include "headers.h"
2
Kevin McKinney54ced002011-10-10 21:01:50 -04003INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
4 UINT addr,
5 PVOID buff,
6 INT len)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07007{
8 int retval = 0;
Kevin McKinney54ced002011-10-10 21:01:50 -04009 USHORT usRetries = 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070010
Kevin McKinney54ced002011-10-10 21:01:50 -040011 if (psIntfAdapter == NULL) {
12 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070013 return -EINVAL;
14 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070015
Kevin McKinney54ced002011-10-10 21:01:50 -040016 if (psIntfAdapter->psAdapter->device_removed == TRUE) {
17 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070018 return -ENODEV;
19 }
20
Kevin McKinney54ced002011-10-10 21:01:50 -040021 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");
Dan Carpenterf05321c2010-11-13 07:37:49 +030023 return -EACCES;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070024 }
25
Kevin McKinney54ced002011-10-10 21:01:50 -040026 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..");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070028 return -EACCES;
29 }
Kevin McKinney54ced002011-10-10 21:01:50 -040030 psIntfAdapter->psAdapter->DeviceAccess = TRUE;
31
32 do {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070033 retval = usb_control_msg(psIntfAdapter->udev,
Kevin McKinney54ced002011-10-10 21:01:50 -040034 usb_rcvctrlpipe(psIntfAdapter->udev, 0),
35 0x02,
36 0xC2,
37 (addr & 0xFFFF),
38 ((addr >> 16) & 0xFFFF),
39 buff,
40 len,
41 5000);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070042
Kevin McKinney54ced002011-10-10 21:01:50 -040043 usRetries++;
44 if (-ENODEV == retval) {
45 psIntfAdapter->psAdapter->device_removed = TRUE;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070046 break;
47 }
48
Kevin McKinney54ced002011-10-10 21:01:50 -040049 } while ((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070050
Kevin McKinney54ced002011-10-10 21:01:50 -040051 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;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070054 return retval;
Kevin McKinney54ced002011-10-10 21:01:50 -040055 } else {
56 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", retval);
57 psIntfAdapter->psAdapter->DeviceAccess = FALSE;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070058 return STATUS_SUCCESS;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070059 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070060}
61
Kevin McKinney54ced002011-10-10 21:01:50 -040062INT 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
122INT BcmRDM(PVOID arg,
123 UINT addr,
124 PVOID buff,
125 INT len)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700126{
127 return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
128}
129
Kevin McKinney54ced002011-10-10 21:01:50 -0400130INT BcmWRM(PVOID arg,
131 UINT addr,
132 PVOID buff,
133 INT len)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700134{
135 return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
136}
137
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700138INT Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter)
139{
140 PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter);
Kevin McKinney54ced002011-10-10 21:01:50 -0400141 INT status = STATUS_SUCCESS;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700142
143 /*
Kevin McKinney54ced002011-10-10 21:01:50 -0400144 * 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 */
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700157
Kevin McKinney54ced002011-10-10 21:01:50 -0400158 /* Killing all the submitted urbs to different end points. */
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700159 Bcm_kill_all_URBs(psIntfAdapter);
160
Kevin McKinney54ced002011-10-10 21:01:50 -0400161 /* 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);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700165
Kevin McKinney54ced002011-10-10 21:01:50 -0400166 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);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700169
Kevin McKinney54ced002011-10-10 21:01:50 -0400170 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);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700173
Kevin McKinney54ced002011-10-10 21:01:50 -0400174 return status;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700175}
176
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700177VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
178{
179 struct urb *tempUrb = NULL;
180 UINT i;
181
Kevin McKinney54ced002011-10-10 21:01:50 -0400182 /*
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 */
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700196
197 /* Cancel submitted Interrupt-URB's */
Kevin McKinney54ced002011-10-10 21:01:50 -0400198 if (psIntfAdapter->psInterruptUrb != NULL) {
199 if (psIntfAdapter->psInterruptUrb->status == -EINPROGRESS)
200 usb_kill_urb(psIntfAdapter->psInterruptUrb);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700201 }
202
203 /* Cancel All submitted TX URB's */
Kevin McKinney54ced002011-10-10 21:01:50 -0400204 for (i = 0; i < MAXIMUM_USB_TCB; i++) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700205 tempUrb = psIntfAdapter->asUsbTcb[i].urb;
Kevin McKinney54ced002011-10-10 21:01:50 -0400206 if (tempUrb) {
207 if (tempUrb->status == -EINPROGRESS)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700208 usb_kill_urb(tempUrb);
209 }
210 }
211
Kevin McKinney54ced002011-10-10 21:01:50 -0400212 for (i = 0; i < MAXIMUM_USB_RCB; i++) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700213 tempUrb = psIntfAdapter->asUsbRcb[i].urb;
Kevin McKinney54ced002011-10-10 21:01:50 -0400214 if (tempUrb) {
215 if (tempUrb->status == -EINPROGRESS)
216 usb_kill_urb(tempUrb);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700217 }
218 }
219
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700220 atomic_set(&psIntfAdapter->uNumTcbUsed, 0);
221 atomic_set(&psIntfAdapter->uCurrTcb, 0);
222
223 atomic_set(&psIntfAdapter->uNumRcbUsed, 0);
224 atomic_set(&psIntfAdapter->uCurrRcb, 0);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700225}
226
227VOID putUsbSuspend(struct work_struct *work)
228{
Kevin McKinney54ced002011-10-10 21:01:50 -0400229 PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
230 struct usb_interface *intf = NULL;
231 psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER, usbSuspendWork);
232 intf = psIntfAdapter->interface;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700233
Kevin McKinney54ced002011-10-10 21:01:50 -0400234 if (psIntfAdapter->bSuspended == FALSE)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700235 usb_autopm_put_interface(intf);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700236}
237