PM / sleep: Asynchronous threads for suspend_noirq
[linux/fpc-iii.git] / drivers / staging / bcm / InterfaceTx.c
blobea7707b8e60e2cdb376514f231a5de66fe3b2b7b
1 #include "headers.h"
3 /*this is transmit call-back(BULK OUT)*/
4 static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/)
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);
13 if (unlikely(netif_msg_tx_done(Adapter)))
14 pr_info(PFX "%s: transmit status %d\n", Adapter->dev->name, urb->status);
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);
25 pTcb->bUsed = false;
26 atomic_dec(&psIntfAdapter->uNumTcbUsed);
30 if (TRUE == psAdapter->bPreparingForLowPowerMode) {
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;
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;
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);
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;
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);
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);
90 err_exit:
91 usb_free_coherent(urb->dev, urb->transfer_buffer_length,
92 urb->transfer_buffer, urb->transfer_dma);
96 static struct bcm_usb_tcb *GetBulkOutTcb(struct bcm_interface_adapter *psIntfAdapter)
98 struct bcm_usb_tcb *pTcb = NULL;
99 UINT index = 0;
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);
113 return pTcb;
116 static int TransmitTcb(struct bcm_interface_adapter *psIntfAdapter, struct bcm_usb_tcb *pTcb, PVOID data, int len)
119 struct urb *urb = pTcb->urb;
120 int retval = 0;
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;
128 memcpy(urb->transfer_buffer, data, len);
129 urb->transfer_buffer_length = len;
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);
143 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* For DMA transfer */
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);
158 return retval;
161 int InterfaceTransmitPacket(PVOID arg, PVOID data, UINT len)
163 struct bcm_usb_tcb *pTcb = NULL;
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;
171 return TransmitTcb(psIntfAdapter, pTcb, data, len);