Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
[pandora-kernel.git] / drivers / staging / bcm / InterfaceTx.c
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