1/* 2* InterfaceIsr.c 3* 4*Copyright (C) 2010 Beceem Communications, Inc. 5* 6*This program is free software: you can redistribute it and/or modify 7*it under the terms of the GNU General Public License version 2 as 8*published by the Free Software Foundation. 9* 10*This program is distributed in the hope that it will be useful,but 11*WITHOUT ANY WARRANTY; without even the implied warranty of 12*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13*See the GNU General Public License for more details. 14* 15*You should have received a copy of the GNU General Public License 16*along with this program. If not, write to the Free Software Foundation, Inc., 17*51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18* 19*/ 20 21 22#include <headers.h> 23 24#ifndef BCM_SHM_INTERFACE 25 26static void read_int_callback(struct urb *urb/*, struct pt_regs *regs*/) 27{ 28 int status = urb->status; 29 PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)urb->context; 30 PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter ; 31 32 if(Adapter->device_removed == TRUE) 33 { 34 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Device has Got Removed."); 35 return ; 36 } 37 38 if(((Adapter->bPreparingForLowPowerMode == TRUE) && (Adapter->bDoSuspend == TRUE)) || 39 psIntfAdapter->bSuspended || 40 psIntfAdapter->bPreparingForBusSuspend) 41 { 42 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Interrupt call back is called while suspending the device"); 43 return ; 44 } 45 46 //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "interrupt urb status %d", status); 47 switch (status) { 48 /* success */ 49 case STATUS_SUCCESS: 50 if ( urb->actual_length ) 51 { 52 53 if(psIntfAdapter->ulInterruptData[1] & 0xFF) 54 { 55 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Got USIM interrupt"); 56 } 57 58 if(psIntfAdapter->ulInterruptData[1] & 0xFF00) 59 { 60 atomic_set(&Adapter->CurrNumFreeTxDesc, 61 (psIntfAdapter->ulInterruptData[1] & 0xFF00) >> 8); 62 atomic_set (&Adapter->uiMBupdate, TRUE); 63 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "TX mailbox contains %d", 64 atomic_read(&Adapter->CurrNumFreeTxDesc)); 65 } 66 if(psIntfAdapter->ulInterruptData[1] >> 16) 67 { 68 Adapter->CurrNumRecvDescs= 69 (psIntfAdapter->ulInterruptData[1] >> 16); 70 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"RX mailbox contains %d", 71 Adapter->CurrNumRecvDescs); 72 InterfaceRx(psIntfAdapter); 73 } 74 75 if(psIntfAdapter->ulInterruptData[1] & FW_UDMA_RESET_DONE) 76 { 77 psIntfAdapter->bUDMAResetDone = TRUE; 78 } 79 80 if(Adapter->fw_download_done && 81 !Adapter->uiFirstInterrupt && 82 atomic_read(&Adapter->CurrNumFreeTxDesc)) 83 { 84 psIntfAdapter->psAdapter->uiFirstInterrupt +=1; 85 wake_up(&Adapter->tx_packet_wait_queue); 86 } 87 if(FALSE == Adapter->waiting_to_fw_download_done) 88 { 89 Adapter->waiting_to_fw_download_done = TRUE; 90 wake_up(&Adapter->ioctl_fw_dnld_wait_queue); 91 } 92 if(!atomic_read(&Adapter->TxPktAvail)) 93 { 94 atomic_set(&Adapter->TxPktAvail, 1); 95 wake_up(&Adapter->tx_packet_wait_queue); 96 } 97 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Firing interrupt in URB"); 98 } 99 break; 100 case -ENOENT : 101 { 102 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"URB has got disconnected ...."); 103 return ; 104 } 105 case -EINPROGRESS: 106 { 107 //This situation may happend when URBunlink is used. for detail check usb_unlink_urb documentation. 108 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Impossibe condition has occured... something very bad is going on"); 109 break ; 110 //return; 111 } 112 case -EPIPE: 113 { 114 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Interrupt IN endPoint has got halted/stalled...need to clear this"); 115 Adapter->bEndPointHalted = TRUE ; 116 wake_up(&Adapter->tx_packet_wait_queue); 117 urb->status = STATUS_SUCCESS ;; 118 return; 119 } 120 /* software-driven interface shutdown */ 121 case -ECONNRESET: //URB got unlinked. 122 case -ESHUTDOWN: // hardware gone. this is the serious problem. 123 //Occurs only when something happens with the host controller device 124 case -ENODEV : //Device got removed 125 case -EINVAL : //Some thing very bad happened with the URB. No description is available. 126 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"interrupt urb error %d", status); 127 urb->status = STATUS_SUCCESS ; 128 break ; 129 //return; 130 default: 131 //This is required to check what is the defaults conditions when it occurs.. 132 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"GOT DEFAULT INTERRUPT URB STATUS :%d..Please Analyze it...", status); 133 break; 134 } 135 136 StartInterruptUrb(psIntfAdapter); 137 138 139} 140 141int CreateInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter) 142{ 143 psIntfAdapter->psInterruptUrb = usb_alloc_urb(0, GFP_KERNEL); 144 if (!psIntfAdapter->psInterruptUrb) 145 { 146 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Cannot allocate interrupt urb"); 147 return -ENOMEM; 148 } 149 psIntfAdapter->psInterruptUrb->transfer_buffer = 150 psIntfAdapter->ulInterruptData; 151 psIntfAdapter->psInterruptUrb->transfer_buffer_length = 152 sizeof(psIntfAdapter->ulInterruptData); 153 154 psIntfAdapter->sIntrIn.int_in_pipe = usb_rcvintpipe(psIntfAdapter->udev, 155 psIntfAdapter->sIntrIn.int_in_endpointAddr); 156 157 usb_fill_int_urb(psIntfAdapter->psInterruptUrb, psIntfAdapter->udev, 158 psIntfAdapter->sIntrIn.int_in_pipe, 159 psIntfAdapter->psInterruptUrb->transfer_buffer, 160 psIntfAdapter->psInterruptUrb->transfer_buffer_length, 161 read_int_callback, psIntfAdapter, 162 psIntfAdapter->sIntrIn.int_in_interval); 163 164 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Interrupt Interval: %d\n", 165 psIntfAdapter->sIntrIn.int_in_interval); 166 return 0; 167} 168 169 170INT StartInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter) 171{ 172 INT status = 0; 173 174 if( FALSE == psIntfAdapter->psAdapter->device_removed && 175 FALSE == psIntfAdapter->psAdapter->bEndPointHalted && 176 FALSE == psIntfAdapter->bSuspended && 177 FALSE == psIntfAdapter->bPreparingForBusSuspend && 178 FALSE == psIntfAdapter->psAdapter->StopAllXaction) 179 { 180 status = usb_submit_urb(psIntfAdapter->psInterruptUrb, GFP_ATOMIC); 181 if (status) 182 { 183 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Cannot send int urb %d\n", status); 184 if(status == -EPIPE) 185 { 186 psIntfAdapter->psAdapter->bEndPointHalted = TRUE ; 187 wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue); 188 } 189 } 190 } 191 return status; 192} 193 194/* 195Function: InterfaceEnableInterrupt 196 197Description: This is the hardware specific Function for configuring 198 and enabling the interrupts on the device. 199 200Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context 201 202 203Return: BCM_STATUS_SUCCESS - If configuring the interrupts was successful. 204 Other - If an error occured. 205*/ 206 207void InterfaceEnableInterrupt(PMINI_ADAPTER Adapter) 208{ 209 210} 211 212/* 213Function: InterfaceDisableInterrupt 214 215Description: This is the hardware specific Function for disabling the interrupts on the device. 216 217Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context 218 219 220Return: BCM_STATUS_SUCCESS - If disabling the interrupts was successful. 221 Other - If an error occured. 222*/ 223 224void InterfaceDisableInterrupt(PMINI_ADAPTER Adapter) 225{ 226 227} 228 229#endif 230 231