at v3.18 213 lines 7.0 kB view raw
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 * This covers the bus err while Idle Request msg 16 * sent down. 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 /* Signalling the cntrl pkt path in Ioctl */ 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 /* since going in Idle mode completed hence making this var false */ 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 /* Signalling the cntrl pkt path in Ioctl*/ 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 * This covers the bus err while shutdown Request 47 * msg sent down. 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 /* Signalling the cntrl pkt path in Ioctl */ 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 * since going in shutdown mode completed hence 65 * making this var false 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 /* Signalling the cntrl pkt path in Ioctl */ 72 wake_up(&ps_adapter->lowpower_mode_wait_queue); 73 } 74 } 75 76 if (ps_adapter->bDoSuspend && *b_power_down_msg) { 77 /* issuing bus suspend request */ 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/*this is transmit call-back(BULK OUT)*/ 86static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/) 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 /* For T3B,INT OUT end point will be used as bulk out end point */ 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; /* For DMA transfer */ 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