blob: bbe909946091c24b284c57ba65f8ac043430d370 [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{
Kevin McKinney41c7b7c2011-11-06 09:40:11 -05008 int bytes;
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 {
Kevin McKinney41c7b7c2011-11-06 09:40:11 -050033 bytes = 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++;
Kevin McKinney41c7b7c2011-11-06 09:40:11 -050044 if (-ENODEV == bytes) {
Kevin McKinney54ced002011-10-10 21:01:50 -040045 psIntfAdapter->psAdapter->device_removed = TRUE;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070046 break;
47 }
48
Kevin McKinney41c7b7c2011-11-06 09:40:11 -050049 } while ((bytes < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070050
Kevin McKinney41c7b7c2011-11-06 09:40:11 -050051 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;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070058}
59
Kevin McKinney54ced002011-10-10 21:01:50 -040060INT 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
120INT BcmRDM(PVOID arg,
121 UINT addr,
122 PVOID buff,
123 INT len)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700124{
125 return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
126}
127
Kevin McKinney54ced002011-10-10 21:01:50 -0400128INT BcmWRM(PVOID arg,
129 UINT addr,
130 PVOID buff,
131 INT len)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700132{
133 return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
134}
135
Kevin McKinney29794602012-05-26 12:05:12 -0400136INT Bcm_clear_halt_of_endpoints(struct bcm_mini_adapter *Adapter)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700137{
138 PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter);
Kevin McKinney54ced002011-10-10 21:01:50 -0400139 INT status = STATUS_SUCCESS;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700140
141 /*
Kevin McKinney54ced002011-10-10 21:01:50 -0400142 * 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 */
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700155
Kevin McKinney54ced002011-10-10 21:01:50 -0400156 /* Killing all the submitted urbs to different end points. */
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700157 Bcm_kill_all_URBs(psIntfAdapter);
158
Kevin McKinney54ced002011-10-10 21:01:50 -0400159 /* 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);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700163
Kevin McKinney54ced002011-10-10 21:01:50 -0400164 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);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700167
Kevin McKinney54ced002011-10-10 21:01:50 -0400168 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);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700171
Kevin McKinney54ced002011-10-10 21:01:50 -0400172 return status;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700173}
174
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700175VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
176{
177 struct urb *tempUrb = NULL;
178 UINT i;
179
Kevin McKinney54ced002011-10-10 21:01:50 -0400180 /*
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 */
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700194
195 /* Cancel submitted Interrupt-URB's */
Kevin McKinney54ced002011-10-10 21:01:50 -0400196 if (psIntfAdapter->psInterruptUrb != NULL) {
197 if (psIntfAdapter->psInterruptUrb->status == -EINPROGRESS)
198 usb_kill_urb(psIntfAdapter->psInterruptUrb);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700199 }
200
201 /* Cancel All submitted TX URB's */
Kevin McKinney54ced002011-10-10 21:01:50 -0400202 for (i = 0; i < MAXIMUM_USB_TCB; i++) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700203 tempUrb = psIntfAdapter->asUsbTcb[i].urb;
Kevin McKinney54ced002011-10-10 21:01:50 -0400204 if (tempUrb) {
205 if (tempUrb->status == -EINPROGRESS)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700206 usb_kill_urb(tempUrb);
207 }
208 }
209
Kevin McKinney54ced002011-10-10 21:01:50 -0400210 for (i = 0; i < MAXIMUM_USB_RCB; i++) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700211 tempUrb = psIntfAdapter->asUsbRcb[i].urb;
Kevin McKinney54ced002011-10-10 21:01:50 -0400212 if (tempUrb) {
213 if (tempUrb->status == -EINPROGRESS)
214 usb_kill_urb(tempUrb);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700215 }
216 }
217
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700218 atomic_set(&psIntfAdapter->uNumTcbUsed, 0);
219 atomic_set(&psIntfAdapter->uCurrTcb, 0);
220
221 atomic_set(&psIntfAdapter->uNumRcbUsed, 0);
222 atomic_set(&psIntfAdapter->uCurrRcb, 0);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700223}
224
225VOID putUsbSuspend(struct work_struct *work)
226{
Kevin McKinney54ced002011-10-10 21:01:50 -0400227 PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
228 struct usb_interface *intf = NULL;
229 psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER, usbSuspendWork);
230 intf = psIntfAdapter->interface;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700231
Kevin McKinney54ced002011-10-10 21:01:50 -0400232 if (psIntfAdapter->bSuspended == FALSE)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700233 usb_autopm_put_interface(intf);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700234}
235