1 #include "headers.h"
2 
InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,UINT addr,PVOID buff,INT len)3 INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter,
4 		UINT addr,
5 		PVOID buff,
6 		INT len)
7 {
8 	int bytes;
9 	USHORT usRetries = 0;
10 
11 	if (psIntfAdapter == NULL) {
12 		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL");
13 		return -EINVAL;
14 	}
15 
16 	if (psIntfAdapter->psAdapter->device_removed == TRUE) {
17 		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed");
18 		return -ENODEV;
19 	}
20 
21 	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");
23 		return -EACCES;
24 	}
25 
26 	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..");
28 		return -EACCES;
29 	}
30 	psIntfAdapter->psAdapter->DeviceAccess = TRUE;
31 
32 	do {
33 		bytes = usb_control_msg(psIntfAdapter->udev,
34 					usb_rcvctrlpipe(psIntfAdapter->udev, 0),
35 					0x02,
36 					0xC2,
37 					(addr & 0xFFFF),
38 					((addr >> 16) & 0xFFFF),
39 					buff,
40 					len,
41 					5000);
42 
43 		usRetries++;
44 		if (-ENODEV == bytes) {
45 			psIntfAdapter->psAdapter->device_removed = TRUE;
46 			break;
47 		}
48 
49 	} while ((bytes < 0) && (usRetries < MAX_RDM_WRM_RETIRES));
50 
51 	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;
58 }
59 
InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter,UINT addr,PVOID buff,INT len)60 INT 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 
BcmRDM(PVOID arg,UINT addr,PVOID buff,INT len)120 INT BcmRDM(PVOID arg,
121 	UINT addr,
122 	PVOID buff,
123 	INT len)
124 {
125 	return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
126 }
127 
BcmWRM(PVOID arg,UINT addr,PVOID buff,INT len)128 INT BcmWRM(PVOID arg,
129 	UINT addr,
130 	PVOID buff,
131 	INT len)
132 {
133 	return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len);
134 }
135 
Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter)136 INT Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter)
137 {
138 	PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter);
139 	INT status = STATUS_SUCCESS;
140 
141 	/*
142 	 * 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 	 */
155 
156 	/* Killing all the submitted urbs to different end points. */
157 	Bcm_kill_all_URBs(psIntfAdapter);
158 
159 	/* 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);
163 
164 	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);
167 
168 	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);
171 
172 	return status;
173 }
174 
Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)175 VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter)
176 {
177 	struct urb *tempUrb = NULL;
178 	UINT i;
179 
180 	/*
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 	 */
194 
195 	/* Cancel submitted Interrupt-URB's */
196 	if (psIntfAdapter->psInterruptUrb != NULL) {
197 		if (psIntfAdapter->psInterruptUrb->status == -EINPROGRESS)
198 			usb_kill_urb(psIntfAdapter->psInterruptUrb);
199 	}
200 
201 	/* Cancel All submitted TX URB's */
202 	for (i = 0; i < MAXIMUM_USB_TCB; i++) {
203 		tempUrb = psIntfAdapter->asUsbTcb[i].urb;
204 		if (tempUrb) {
205 			if (tempUrb->status == -EINPROGRESS)
206 				usb_kill_urb(tempUrb);
207 		}
208 	}
209 
210 	for (i = 0; i < MAXIMUM_USB_RCB; i++) {
211 		tempUrb = psIntfAdapter->asUsbRcb[i].urb;
212 		if (tempUrb) {
213 			if (tempUrb->status == -EINPROGRESS)
214 				usb_kill_urb(tempUrb);
215 		}
216 	}
217 
218 	atomic_set(&psIntfAdapter->uNumTcbUsed, 0);
219 	atomic_set(&psIntfAdapter->uCurrTcb, 0);
220 
221 	atomic_set(&psIntfAdapter->uNumRcbUsed, 0);
222 	atomic_set(&psIntfAdapter->uCurrRcb, 0);
223 }
224 
putUsbSuspend(struct work_struct * work)225 VOID putUsbSuspend(struct work_struct *work)
226 {
227 	PS_INTERFACE_ADAPTER psIntfAdapter = NULL;
228 	struct usb_interface *intf = NULL;
229 	psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER, usbSuspendWork);
230 	intf = psIntfAdapter->interface;
231 
232 	if (psIntfAdapter->bSuspended == FALSE)
233 		usb_autopm_put_interface(intf);
234 }
235 
236