diff options
Diffstat (limited to 'drivers/staging/bcm/InterfaceTx.c')
-rw-r--r-- | drivers/staging/bcm/InterfaceTx.c | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/drivers/staging/bcm/InterfaceTx.c b/drivers/staging/bcm/InterfaceTx.c new file mode 100644 index 00000000000..771f7b34d2e --- /dev/null +++ b/drivers/staging/bcm/InterfaceTx.c | |||
@@ -0,0 +1,259 @@ | |||
1 | #include "headers.h" | ||
2 | |||
3 | #ifndef BCM_SHM_INTERFACE | ||
4 | |||
5 | /* | ||
6 | Function: InterfaceTxDataPacket | ||
7 | |||
8 | Description: This is the hardware specific Function for Transmitting | ||
9 | data packet to the device. | ||
10 | |||
11 | Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context | ||
12 | PVOID Packet - Packet Containing the data to be transmitted | ||
13 | USHORT usVcid - VCID on which data packet is to be sent | ||
14 | |||
15 | |||
16 | Return: BCM_STATUS_SUCCESS - If Tx was successful. | ||
17 | Other - If an error occured. | ||
18 | */ | ||
19 | |||
20 | ULONG InterfaceTxDataPacket(PMINI_ADAPTER Adapter,PVOID Packet,USHORT usVcid) | ||
21 | { | ||
22 | ULONG Status = 0; | ||
23 | return Status; | ||
24 | } | ||
25 | |||
26 | /* | ||
27 | Function: InterfaceTxControlPacket | ||
28 | |||
29 | Description: This is the hardware specific Function for Transmitting | ||
30 | control packet to the device. | ||
31 | |||
32 | Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context | ||
33 | PVOID pvBuffer - Buffer containg control packet | ||
34 | UINT uiBufferLength - Buffer Length | ||
35 | |||
36 | Return: BCM_STATUS_SUCCESS - If control packet transmit was successful. | ||
37 | Other - If an error occured. | ||
38 | */ | ||
39 | |||
40 | ULONG InterfaceTxControlPacket(PMINI_ADAPTER Adapter,PVOID pvBuffer,UINT uiBufferLength) | ||
41 | { | ||
42 | ULONG Status = 0; | ||
43 | |||
44 | |||
45 | |||
46 | return Status; | ||
47 | } | ||
48 | /*this is transmit call-back(BULK OUT)*/ | ||
49 | static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/) | ||
50 | { | ||
51 | PUSB_TCB pTcb= (PUSB_TCB)urb->context; | ||
52 | PS_INTERFACE_ADAPTER psIntfAdapter = pTcb->psIntfAdapter; | ||
53 | CONTROL_MESSAGE *pControlMsg = (CONTROL_MESSAGE *)urb->transfer_buffer; | ||
54 | PMINI_ADAPTER psAdapter = psIntfAdapter->psAdapter ; | ||
55 | BOOLEAN bpowerDownMsg = FALSE ; | ||
56 | PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); | ||
57 | #if 0 | ||
58 | struct timeval tv; | ||
59 | UINT time_ms = 0; | ||
60 | #endif | ||
61 | if(urb->status != STATUS_SUCCESS) | ||
62 | { | ||
63 | if(urb->status == -EPIPE) | ||
64 | { | ||
65 | psIntfAdapter->psAdapter->bEndPointHalted = TRUE ; | ||
66 | wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue); | ||
67 | } | ||
68 | else | ||
69 | { | ||
70 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Tx URB has got cancelled. status :%d", urb->status); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | pTcb->bUsed = FALSE; | ||
75 | atomic_dec(&psIntfAdapter->uNumTcbUsed); | ||
76 | |||
77 | |||
78 | |||
79 | if(TRUE == psAdapter->bPreparingForLowPowerMode) | ||
80 | { | ||
81 | #if 0 | ||
82 | do_gettimeofday(&tv); | ||
83 | time_ms = tv.tv_sec *1000 + tv.tv_usec/1000; | ||
84 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " %s Idle Mode ACK_Sent got from device at time :0x%x", __FUNCTION__, time_ms); | ||
85 | #endif | ||
86 | |||
87 | if(((pControlMsg->szData[0] == GO_TO_IDLE_MODE_PAYLOAD) && | ||
88 | (pControlMsg->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE))) | ||
89 | |||
90 | { | ||
91 | bpowerDownMsg = TRUE ; | ||
92 | //This covers the bus err while Idle Request msg sent down. | ||
93 | if(urb->status != STATUS_SUCCESS) | ||
94 | { | ||
95 | psAdapter->bPreparingForLowPowerMode = FALSE ; | ||
96 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Idle Mode Request msg failed to reach to Modem"); | ||
97 | //Signalling the cntrl pkt path in Ioctl | ||
98 | wake_up(&psAdapter->lowpower_mode_wait_queue); | ||
99 | StartInterruptUrb(psIntfAdapter); | ||
100 | goto err_exit; | ||
101 | } | ||
102 | |||
103 | if(psAdapter->bDoSuspend == FALSE) | ||
104 | { | ||
105 | psAdapter->IdleMode = TRUE; | ||
106 | //since going in Idle mode completed hence making this var false; | ||
107 | psAdapter->bPreparingForLowPowerMode = FALSE ; | ||
108 | |||
109 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Host Entered in Idle Mode State..."); | ||
110 | //Signalling the cntrl pkt path in Ioctl | ||
111 | wake_up(&psAdapter->lowpower_mode_wait_queue); | ||
112 | } | ||
113 | |||
114 | } | ||
115 | else if((pControlMsg->Leader.Status == LINK_UP_CONTROL_REQ) && | ||
116 | (pControlMsg->szData[0] == LINK_UP_ACK) && | ||
117 | (pControlMsg->szData[1] == LINK_SHUTDOWN_REQ_FROM_FIRMWARE) && | ||
118 | (pControlMsg->szData[2] == SHUTDOWN_ACK_FROM_DRIVER)) | ||
119 | { | ||
120 | //This covers the bus err while shutdown Request msg sent down. | ||
121 | if(urb->status != STATUS_SUCCESS) | ||
122 | { | ||
123 | psAdapter->bPreparingForLowPowerMode = FALSE ; | ||
124 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Shutdown Request Msg failed to reach to Modem"); | ||
125 | //Signalling the cntrl pkt path in Ioctl | ||
126 | wake_up(&psAdapter->lowpower_mode_wait_queue); | ||
127 | StartInterruptUrb(psIntfAdapter); | ||
128 | goto err_exit; | ||
129 | } | ||
130 | |||
131 | bpowerDownMsg = TRUE ; | ||
132 | if(psAdapter->bDoSuspend == FALSE) | ||
133 | { | ||
134 | psAdapter->bShutStatus = TRUE; | ||
135 | //since going in shutdown mode completed hence making this var false; | ||
136 | psAdapter->bPreparingForLowPowerMode = FALSE ; | ||
137 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Host Entered in shutdown Mode State..."); | ||
138 | //Signalling the cntrl pkt path in Ioctl | ||
139 | wake_up(&psAdapter->lowpower_mode_wait_queue); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | if(psAdapter->bDoSuspend && bpowerDownMsg) | ||
144 | { | ||
145 | //issuing bus suspend request | ||
146 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Issuing the Bus suspend request to USB stack"); | ||
147 | psIntfAdapter->bPreparingForBusSuspend = TRUE; | ||
148 | schedule_work(&psIntfAdapter->usbSuspendWork); | ||
149 | |||
150 | } | ||
151 | |||
152 | } | ||
153 | |||
154 | err_exit : | ||
155 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) | ||
156 | usb_buffer_free(urb->dev, urb->transfer_buffer_length, | ||
157 | urb->transfer_buffer, urb->transfer_dma); | ||
158 | #else | ||
159 | usb_free_coherent(urb->dev, urb->transfer_buffer_length, | ||
160 | urb->transfer_buffer, urb->transfer_dma); | ||
161 | #endif | ||
162 | } | ||
163 | |||
164 | |||
165 | static __inline PUSB_TCB GetBulkOutTcb(PS_INTERFACE_ADAPTER psIntfAdapter) | ||
166 | { | ||
167 | PUSB_TCB pTcb = NULL; | ||
168 | UINT index = 0; | ||
169 | |||
170 | if((atomic_read(&psIntfAdapter->uNumTcbUsed) < MAXIMUM_USB_TCB) && | ||
171 | (psIntfAdapter->psAdapter->StopAllXaction ==FALSE)) | ||
172 | { | ||
173 | index = atomic_read(&psIntfAdapter->uCurrTcb); | ||
174 | pTcb = &psIntfAdapter->asUsbTcb[index]; | ||
175 | pTcb->bUsed = TRUE; | ||
176 | pTcb->psIntfAdapter= psIntfAdapter; | ||
177 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Got Tx desc %d used %d", | ||
178 | index, atomic_read(&psIntfAdapter->uNumTcbUsed)); | ||
179 | index = (index + 1) % MAXIMUM_USB_TCB; | ||
180 | atomic_set(&psIntfAdapter->uCurrTcb, index); | ||
181 | atomic_inc(&psIntfAdapter->uNumTcbUsed); | ||
182 | } | ||
183 | return pTcb; | ||
184 | } | ||
185 | |||
186 | static __inline int TransmitTcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_TCB pTcb, PVOID data, int len) | ||
187 | { | ||
188 | |||
189 | struct urb *urb = pTcb->urb; | ||
190 | int retval = 0; | ||
191 | |||
192 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) | ||
193 | urb->transfer_buffer = usb_buffer_alloc(psIntfAdapter->udev, len, | ||
194 | GFP_ATOMIC, &urb->transfer_dma); | ||
195 | #else | ||
196 | urb->transfer_buffer = usb_alloc_coherent(psIntfAdapter->udev, len, | ||
197 | GFP_ATOMIC, &urb->transfer_dma); | ||
198 | #endif | ||
199 | |||
200 | if (!urb->transfer_buffer) | ||
201 | { | ||
202 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Error allocating memory\n"); | ||
203 | return -ENOMEM; | ||
204 | } | ||
205 | memcpy(urb->transfer_buffer, data, len); | ||
206 | urb->transfer_buffer_length = len; | ||
207 | |||
208 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending Bulk out packet\n"); | ||
209 | //For T3B,INT OUT end point will be used as bulk out end point | ||
210 | if((psIntfAdapter->psAdapter->chip_id == T3B) && (psIntfAdapter->bHighSpeedDevice == TRUE)) | ||
211 | { | ||
212 | usb_fill_int_urb(urb, psIntfAdapter->udev, | ||
213 | psIntfAdapter->sBulkOut.bulk_out_pipe, | ||
214 | urb->transfer_buffer, len, write_bulk_callback, pTcb, | ||
215 | psIntfAdapter->sBulkOut.int_out_interval); | ||
216 | } | ||
217 | else | ||
218 | { | ||
219 | usb_fill_bulk_urb(urb, psIntfAdapter->udev, | ||
220 | psIntfAdapter->sBulkOut.bulk_out_pipe, | ||
221 | urb->transfer_buffer, len, write_bulk_callback, pTcb); | ||
222 | } | ||
223 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* For DMA transfer */ | ||
224 | |||
225 | if(FALSE == psIntfAdapter->psAdapter->device_removed && | ||
226 | FALSE == psIntfAdapter->psAdapter->bEndPointHalted && | ||
227 | FALSE == psIntfAdapter->bSuspended && | ||
228 | FALSE == psIntfAdapter->bPreparingForBusSuspend) | ||
229 | { | ||
230 | retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
231 | if (retval) | ||
232 | { | ||
233 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "failed submitting write urb, error %d", retval); | ||
234 | if(retval == -EPIPE) | ||
235 | { | ||
236 | psIntfAdapter->psAdapter->bEndPointHalted = TRUE ; | ||
237 | wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue); | ||
238 | } | ||
239 | } | ||
240 | } | ||
241 | return retval; | ||
242 | } | ||
243 | |||
244 | int InterfaceTransmitPacket(PVOID arg, PVOID data, UINT len) | ||
245 | { | ||
246 | PUSB_TCB pTcb= NULL; | ||
247 | |||
248 | PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg; | ||
249 | pTcb= GetBulkOutTcb(psIntfAdapter); | ||
250 | if(pTcb == NULL) | ||
251 | { | ||
252 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "No URB to transmit packet, dropping packet"); | ||
253 | return -EFAULT; | ||
254 | } | ||
255 | return TransmitTcb(psIntfAdapter, pTcb, data, len); | ||
256 | } | ||
257 | |||
258 | #endif | ||
259 | |||