1#include "headers.h"
2
3static void prepare_low_power_mode(struct urb *urb,
4 struct bcm_interface_adapter *interface,
5 struct bcm_mini_adapter *ps_adapter,
6 struct bcm_mini_adapter *ad,
7 struct bcm_link_request *p_control_msg,
8 bool *b_power_down_msg)
9{
10 if (((p_control_msg->szData[0] == GO_TO_IDLE_MODE_PAYLOAD) &&
11 (p_control_msg->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE))) {
12
13 *b_power_down_msg = TRUE;
14
15
16
17
18 if (urb->status != STATUS_SUCCESS) {
19 ps_adapter->bPreparingForLowPowerMode = false;
20 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, NEXT_SEND,
21 DBG_LVL_ALL,
22 "Idle Mode Request msg failed to reach to Modem");
23
24 wake_up(&ps_adapter->lowpower_mode_wait_queue);
25 StartInterruptUrb(interface);
26 return;
27 }
28
29 if (ps_adapter->bDoSuspend == false) {
30 ps_adapter->IdleMode = TRUE;
31
32 ps_adapter->bPreparingForLowPowerMode = false;
33
34 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, NEXT_SEND,
35 DBG_LVL_ALL,
36 "Host Entered in Idle Mode State...");
37
38 wake_up(&ps_adapter->lowpower_mode_wait_queue);
39 }
40
41 } else if ((p_control_msg->Leader.Status == LINK_UP_CONTROL_REQ) &&
42 (p_control_msg->szData[0] == LINK_UP_ACK) &&
43 (p_control_msg->szData[1] == LINK_SHUTDOWN_REQ_FROM_FIRMWARE) &&
44 (p_control_msg->szData[2] == SHUTDOWN_ACK_FROM_DRIVER)) {
45
46
47
48
49 if (urb->status != STATUS_SUCCESS) {
50 ps_adapter->bPreparingForLowPowerMode = false;
51 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, NEXT_SEND,
52 DBG_LVL_ALL,
53 "Shutdown Request Msg failed to reach to Modem");
54
55 wake_up(&ps_adapter->lowpower_mode_wait_queue);
56 StartInterruptUrb(interface);
57 return;
58 }
59
60 *b_power_down_msg = TRUE;
61 if (ps_adapter->bDoSuspend == false) {
62 ps_adapter->bShutStatus = TRUE;
63
64
65
66
67 ps_adapter->bPreparingForLowPowerMode = false;
68 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, NEXT_SEND,
69 DBG_LVL_ALL,
70 "Host Entered in shutdown Mode State...");
71
72 wake_up(&ps_adapter->lowpower_mode_wait_queue);
73 }
74 }
75
76 if (ps_adapter->bDoSuspend && *b_power_down_msg) {
77
78 BCM_DEBUG_PRINT(ad, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,
79 "Issuing the Bus suspend request to USB stack");
80 interface->bPreparingForBusSuspend = TRUE;
81 schedule_work(&interface->usbSuspendWork);
82 }
83}
84
85
86static void write_bulk_callback(struct urb *urb)
87{
88 struct bcm_usb_tcb *pTcb = (struct bcm_usb_tcb *)urb->context;
89 struct bcm_interface_adapter *psIntfAdapter = pTcb->psIntfAdapter;
90 struct bcm_link_request *pControlMsg =
91 (struct bcm_link_request *)urb->transfer_buffer;
92 struct bcm_mini_adapter *psAdapter = psIntfAdapter->psAdapter;
93 bool bpowerDownMsg = false;
94 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
95
96 if (unlikely(netif_msg_tx_done(Adapter)))
97 pr_info(PFX "%s: transmit status %d\n", Adapter->dev->name,
98 urb->status);
99
100 if (urb->status != STATUS_SUCCESS) {
101 if (urb->status == -EPIPE) {
102 psIntfAdapter->psAdapter->bEndPointHalted = TRUE;
103 wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
104 } else {
105 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND,
106 DBG_LVL_ALL,
107 "Tx URB has got cancelled. status :%d",
108 urb->status);
109 }
110 }
111
112 pTcb->bUsed = false;
113 atomic_dec(&psIntfAdapter->uNumTcbUsed);
114
115 if (TRUE == psAdapter->bPreparingForLowPowerMode) {
116 prepare_low_power_mode(urb, psIntfAdapter, psAdapter, Adapter,
117 pControlMsg, &bpowerDownMsg);
118 }
119
120 usb_free_coherent(urb->dev, urb->transfer_buffer_length,
121 urb->transfer_buffer, urb->transfer_dma);
122}
123
124
125static struct bcm_usb_tcb *GetBulkOutTcb(struct bcm_interface_adapter *psIntfAdapter)
126{
127 struct bcm_usb_tcb *pTcb = NULL;
128 UINT index = 0;
129
130 if ((atomic_read(&psIntfAdapter->uNumTcbUsed) < MAXIMUM_USB_TCB) &&
131 (psIntfAdapter->psAdapter->StopAllXaction == false)) {
132 index = atomic_read(&psIntfAdapter->uCurrTcb);
133 pTcb = &psIntfAdapter->asUsbTcb[index];
134 pTcb->bUsed = TRUE;
135 pTcb->psIntfAdapter = psIntfAdapter;
136 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX,
137 NEXT_SEND, DBG_LVL_ALL,
138 "Got Tx desc %d used %d",
139 index,
140 atomic_read(&psIntfAdapter->uNumTcbUsed));
141 index = (index + 1) % MAXIMUM_USB_TCB;
142 atomic_set(&psIntfAdapter->uCurrTcb, index);
143 atomic_inc(&psIntfAdapter->uNumTcbUsed);
144 }
145 return pTcb;
146}
147
148static int TransmitTcb(struct bcm_interface_adapter *psIntfAdapter,
149 struct bcm_usb_tcb *pTcb, PVOID data, int len)
150{
151
152 struct urb *urb = pTcb->urb;
153 int retval = 0;
154
155 urb->transfer_buffer = usb_alloc_coherent(psIntfAdapter->udev, len,
156 GFP_ATOMIC, &urb->transfer_dma);
157 if (!urb->transfer_buffer) {
158 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
159 "Error allocating memory\n");
160 return -ENOMEM;
161 }
162 memcpy(urb->transfer_buffer, data, len);
163 urb->transfer_buffer_length = len;
164
165 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX, NEXT_SEND,
166 DBG_LVL_ALL, "Sending Bulk out packet\n");
167
168 if ((psIntfAdapter->psAdapter->chip_id == T3B) &&
169 (psIntfAdapter->bHighSpeedDevice == TRUE)) {
170 usb_fill_int_urb(urb, psIntfAdapter->udev,
171 psIntfAdapter->sBulkOut.bulk_out_pipe,
172 urb->transfer_buffer, len, write_bulk_callback, pTcb,
173 psIntfAdapter->sBulkOut.int_out_interval);
174 } else {
175 usb_fill_bulk_urb(urb, psIntfAdapter->udev,
176 psIntfAdapter->sBulkOut.bulk_out_pipe,
177 urb->transfer_buffer, len, write_bulk_callback, pTcb);
178 }
179 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
180
181 if (false == psIntfAdapter->psAdapter->device_removed &&
182 false == psIntfAdapter->psAdapter->bEndPointHalted &&
183 false == psIntfAdapter->bSuspended &&
184 false == psIntfAdapter->bPreparingForBusSuspend) {
185 retval = usb_submit_urb(urb, GFP_ATOMIC);
186 if (retval) {
187 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_TX,
188 NEXT_SEND, DBG_LVL_ALL,
189 "failed submitting write urb, error %d",
190 retval);
191 if (retval == -EPIPE) {
192 psIntfAdapter->psAdapter->bEndPointHalted = TRUE;
193 wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
194 }
195 }
196 }
197 return retval;
198}
199
200int InterfaceTransmitPacket(PVOID arg, PVOID data, UINT len)
201{
202 struct bcm_usb_tcb *pTcb = NULL;
203 struct bcm_interface_adapter *psIntfAdapter = arg;
204
205 pTcb = GetBulkOutTcb(psIntfAdapter);
206 if (pTcb == NULL) {
207 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0,
208 "No URB to transmit packet, dropping packet");
209 return -EFAULT;
210 }
211 return TransmitTcb(psIntfAdapter, pTcb, data, len);
212}
213
214