]> Pileus Git - ~andy/linux/blob - drivers/staging/bcm/InterfaceTx.c
Merge branch 'msm-next' of git://people.freedesktop.org/~robclark/linux into drm...
[~andy/linux] / drivers / staging / bcm / InterfaceTx.c
1 #include "headers.h"
2
3 /*this is transmit call-back(BULK OUT)*/
4 static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/)
5 {
6         struct bcm_usb_tcb *pTcb = (struct bcm_usb_tcb *)urb->context;
7         struct bcm_interface_adapter *psIntfAdapter = pTcb->psIntfAdapter;
8         struct bcm_link_request *pControlMsg = (struct bcm_link_request *)urb->transfer_buffer;
9         struct bcm_mini_adapter *psAdapter = psIntfAdapter->psAdapter;
10         bool bpowerDownMsg = false;
11         struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
12
13         if (unlikely(netif_msg_tx_done(Adapter)))
14                 pr_info(PFX "%s: transmit status %d\n", Adapter->dev->name, urb->status);
15
16         if (urb->status != STATUS_SUCCESS) {
17                 if (urb->status == -EPIPE) {
18                         psIntfAdapter->psAdapter->bEndPointHalted = TRUE;
19                         wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
20                 } else {
21                         BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Tx URB has got cancelled. status :%d", urb->status);
22                 }
23         }
24
25         pTcb->bUsed = false;
26         atomic_dec(&psIntfAdapter->uNumTcbUsed);
27
28
29
30         if (TRUE == psAdapter->bPreparingForLowPowerMode) {
31
32                 if (((pControlMsg->szData[0] == GO_TO_IDLE_MODE_PAYLOAD) &&
33                         (pControlMsg->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE))) {
34                         bpowerDownMsg = TRUE;
35                         /* This covers the bus err while Idle Request msg sent down. */
36                         if (urb->status != STATUS_SUCCESS) {
37                                 psAdapter->bPreparingForLowPowerMode = false;
38                                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Idle Mode Request msg failed to reach to Modem");
39                                 /* Signalling the cntrl pkt path in Ioctl */
40                                 wake_up(&psAdapter->lowpower_mode_wait_queue);
41                                 StartInterruptUrb(psIntfAdapter);
42                                 goto err_exit;
43                         }
44
45                         if (psAdapter->bDoSuspend == false) {
46                                 psAdapter->IdleMode = TRUE;
47                                 /* since going in Idle mode completed hence making this var false */
48                                 psAdapter->bPreparingForLowPowerMode = false;
49
50                                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Host Entered in Idle Mode State...");
51                                 /* Signalling the cntrl pkt path in Ioctl*/
52                                 wake_up(&psAdapter->lowpower_mode_wait_queue);
53                         }
54
55                 } else if ((pControlMsg->Leader.Status == LINK_UP_CONTROL_REQ) &&
56                         (pControlMsg->szData[0] == LINK_UP_ACK) &&
57                         (pControlMsg->szData[1] == LINK_SHUTDOWN_REQ_FROM_FIRMWARE)  &&
58                         (pControlMsg->szData[2] == SHUTDOWN_ACK_FROM_DRIVER)) {
59                         /* This covers the bus err while shutdown Request msg sent down. */
60                         if (urb->status != STATUS_SUCCESS) {
61                                 psAdapter->bPreparingForLowPowerMode = false;
62                                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Shutdown Request Msg failed to reach to Modem");
63                                 /* Signalling the cntrl pkt path in Ioctl */
64                                 wake_up(&psAdapter->lowpower_mode_wait_queue);
65                                 StartInterruptUrb(psIntfAdapter);
66                                 goto err_exit;
67                         }
68
69                         bpowerDownMsg = TRUE;
70                         if (psAdapter->bDoSuspend == false) {
71                                 psAdapter->bShutStatus = TRUE;
72                                 /* since going in shutdown mode completed hence making this var false */
73                                 psAdapter->bPreparingForLowPowerMode = false;
74                                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Host Entered in shutdown Mode State...");
75                                 /* Signalling the cntrl pkt path in Ioctl */
76                                 wake_up(&psAdapter->lowpower_mode_wait_queue);
77                         }
78                 }
79
80                 if (psAdapter->bDoSuspend && bpowerDownMsg) {
81                         /* issuing bus suspend request */
82                         BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Issuing the Bus suspend request to USB stack");
83                         psIntfAdapter->bPreparingForBusSuspend = TRUE;
84                         schedule_work(&psIntfAdapter->usbSuspendWork);
85
86                 }
87
88         }
89
90 err_exit:
91         usb_free_coherent(urb->dev, urb->transfer_buffer_length,
92                         urb->transfer_buffer, urb->transfer_dma);
93 }
94
95
96 static struct bcm_usb_tcb *GetBulkOutTcb(struct bcm_interface_adapter *psIntfAdapter)
97 {
98         struct bcm_usb_tcb *pTcb = NULL;
99         UINT index = 0;
100
101         if ((atomic_read(&psIntfAdapter->uNumTcbUsed) < MAXIMUM_USB_TCB) &&
102                 (psIntfAdapter->psAdapter->StopAllXaction == false)) {
103                 index = atomic_read(&psIntfAdapter->uCurrTcb);
104                 pTcb = &psIntfAdapter->asUsbTcb[index];
105                 pTcb->bUsed = TRUE;
106                 pTcb->psIntfAdapter = psIntfAdapter;
107                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Got Tx desc %d used %d",
108                         index, atomic_read(&psIntfAdapter->uNumTcbUsed));
109                 index = (index + 1) % MAXIMUM_USB_TCB;
110                 atomic_set(&psIntfAdapter->uCurrTcb, index);
111                 atomic_inc(&psIntfAdapter->uNumTcbUsed);
112         }
113         return pTcb;
114 }
115
116 static int TransmitTcb(struct bcm_interface_adapter *psIntfAdapter, struct bcm_usb_tcb *pTcb, PVOID data, int len)
117 {
118
119         struct urb *urb = pTcb->urb;
120         int retval = 0;
121
122         urb->transfer_buffer = usb_alloc_coherent(psIntfAdapter->udev, len,
123                                                 GFP_ATOMIC, &urb->transfer_dma);
124         if (!urb->transfer_buffer) {
125                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Error allocating memory\n");
126                 return  -ENOMEM;
127         }
128         memcpy(urb->transfer_buffer, data, len);
129         urb->transfer_buffer_length = len;
130
131         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending Bulk out packet\n");
132         /* For T3B,INT OUT end point will be used as bulk out end point */
133         if ((psIntfAdapter->psAdapter->chip_id == T3B) && (psIntfAdapter->bHighSpeedDevice == TRUE)) {
134                 usb_fill_int_urb(urb, psIntfAdapter->udev,
135                         psIntfAdapter->sBulkOut.bulk_out_pipe,
136                         urb->transfer_buffer, len, write_bulk_callback, pTcb,
137                         psIntfAdapter->sBulkOut.int_out_interval);
138         } else {
139         usb_fill_bulk_urb(urb, psIntfAdapter->udev,
140                   psIntfAdapter->sBulkOut.bulk_out_pipe,
141                   urb->transfer_buffer, len, write_bulk_callback, pTcb);
142         }
143         urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* For DMA transfer */
144
145         if (false == psIntfAdapter->psAdapter->device_removed &&
146            false == psIntfAdapter->psAdapter->bEndPointHalted &&
147            false == psIntfAdapter->bSuspended &&
148            false == psIntfAdapter->bPreparingForBusSuspend) {
149                 retval = usb_submit_urb(urb, GFP_ATOMIC);
150                 if (retval) {
151                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "failed submitting write urb, error %d", retval);
152                         if (retval == -EPIPE) {
153                                 psIntfAdapter->psAdapter->bEndPointHalted = TRUE;
154                                 wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
155                         }
156                 }
157         }
158         return retval;
159 }
160
161 int InterfaceTransmitPacket(PVOID arg, PVOID data, UINT len)
162 {
163         struct bcm_usb_tcb *pTcb = NULL;
164
165         struct bcm_interface_adapter *psIntfAdapter = arg;
166         pTcb = GetBulkOutTcb(psIntfAdapter);
167         if (pTcb == NULL) {
168                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "No URB to transmit packet, dropping packet");
169                 return -EFAULT;
170         }
171         return TransmitTcb(psIntfAdapter, pTcb, data, len);
172 }
173
174