| #include "headers.h" | |
| static void read_int_callback(struct urb *urb/*, struct pt_regs *regs*/) | |
| { | |
| int status = urb->status; | |
| struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)urb->context; | |
| struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter ; | |
| if (netif_msg_intr(Adapter)) | |
| pr_info(PFX "%s: interrupt status %d\n", | |
| Adapter->dev->name, status); | |
| if(Adapter->device_removed == TRUE) | |
| { | |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Device has Got Removed."); | |
| return ; | |
| } | |
| if(((Adapter->bPreparingForLowPowerMode == TRUE) && (Adapter->bDoSuspend == TRUE)) || | |
| psIntfAdapter->bSuspended || | |
| psIntfAdapter->bPreparingForBusSuspend) | |
| { | |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Interrupt call back is called while suspending the device"); | |
| return ; | |
| } | |
| //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "interrupt urb status %d", status); | |
| switch (status) { | |
| /* success */ | |
| case STATUS_SUCCESS: | |
| if ( urb->actual_length ) | |
| { | |
| if(psIntfAdapter->ulInterruptData[1] & 0xFF) | |
| { | |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Got USIM interrupt"); | |
| } | |
| if(psIntfAdapter->ulInterruptData[1] & 0xFF00) | |
| { | |
| atomic_set(&Adapter->CurrNumFreeTxDesc, | |
| (psIntfAdapter->ulInterruptData[1] & 0xFF00) >> 8); | |
| atomic_set (&Adapter->uiMBupdate, TRUE); | |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "TX mailbox contains %d", | |
| atomic_read(&Adapter->CurrNumFreeTxDesc)); | |
| } | |
| if(psIntfAdapter->ulInterruptData[1] >> 16) | |
| { | |
| Adapter->CurrNumRecvDescs= | |
| (psIntfAdapter->ulInterruptData[1] >> 16); | |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"RX mailbox contains %d", | |
| Adapter->CurrNumRecvDescs); | |
| InterfaceRx(psIntfAdapter); | |
| } | |
| if(Adapter->fw_download_done && | |
| !Adapter->downloadDDR && | |
| atomic_read(&Adapter->CurrNumFreeTxDesc)) | |
| { | |
| psIntfAdapter->psAdapter->downloadDDR +=1; | |
| wake_up(&Adapter->tx_packet_wait_queue); | |
| } | |
| if(FALSE == Adapter->waiting_to_fw_download_done) | |
| { | |
| Adapter->waiting_to_fw_download_done = TRUE; | |
| wake_up(&Adapter->ioctl_fw_dnld_wait_queue); | |
| } | |
| if(!atomic_read(&Adapter->TxPktAvail)) | |
| { | |
| atomic_set(&Adapter->TxPktAvail, 1); | |
| wake_up(&Adapter->tx_packet_wait_queue); | |
| } | |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Firing interrupt in URB"); | |
| } | |
| break; | |
| case -ENOENT : | |
| { | |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"URB has got disconnected ...."); | |
| return ; | |
| } | |
| case -EINPROGRESS: | |
| { | |
| //This situation may happened when URBunlink is used. for detail check usb_unlink_urb documentation. | |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Impossibe condition has occurred... something very bad is going on"); | |
| break ; | |
| //return; | |
| } | |
| case -EPIPE: | |
| { | |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Interrupt IN endPoint has got halted/stalled...need to clear this"); | |
| Adapter->bEndPointHalted = TRUE ; | |
| wake_up(&Adapter->tx_packet_wait_queue); | |
| urb->status = STATUS_SUCCESS ; | |
| return; | |
| } | |
| /* software-driven interface shutdown */ | |
| case -ECONNRESET: //URB got unlinked. | |
| case -ESHUTDOWN: // hardware gone. this is the serious problem. | |
| //Occurs only when something happens with the host controller device | |
| case -ENODEV : //Device got removed | |
| case -EINVAL : //Some thing very bad happened with the URB. No description is available. | |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"interrupt urb error %d", status); | |
| urb->status = STATUS_SUCCESS ; | |
| break ; | |
| //return; | |
| default: | |
| //This is required to check what is the defaults conditions when it occurs.. | |
| BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"GOT DEFAULT INTERRUPT URB STATUS :%d..Please Analyze it...", status); | |
| break; | |
| } | |
| StartInterruptUrb(psIntfAdapter); | |
| } | |
| int CreateInterruptUrb(struct bcm_interface_adapter *psIntfAdapter) | |
| { | |
| psIntfAdapter->psInterruptUrb = usb_alloc_urb(0, GFP_KERNEL); | |
| if (!psIntfAdapter->psInterruptUrb) | |
| { | |
| BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Cannot allocate interrupt urb"); | |
| return -ENOMEM; | |
| } | |
| psIntfAdapter->psInterruptUrb->transfer_buffer = | |
| psIntfAdapter->ulInterruptData; | |
| psIntfAdapter->psInterruptUrb->transfer_buffer_length = | |
| sizeof(psIntfAdapter->ulInterruptData); | |
| psIntfAdapter->sIntrIn.int_in_pipe = usb_rcvintpipe(psIntfAdapter->udev, | |
| psIntfAdapter->sIntrIn.int_in_endpointAddr); | |
| usb_fill_int_urb(psIntfAdapter->psInterruptUrb, psIntfAdapter->udev, | |
| psIntfAdapter->sIntrIn.int_in_pipe, | |
| psIntfAdapter->psInterruptUrb->transfer_buffer, | |
| psIntfAdapter->psInterruptUrb->transfer_buffer_length, | |
| read_int_callback, psIntfAdapter, | |
| psIntfAdapter->sIntrIn.int_in_interval); | |
| BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Interrupt Interval: %d\n", | |
| psIntfAdapter->sIntrIn.int_in_interval); | |
| return 0; | |
| } | |
| INT StartInterruptUrb(struct bcm_interface_adapter *psIntfAdapter) | |
| { | |
| INT status = 0; | |
| if( FALSE == psIntfAdapter->psAdapter->device_removed && | |
| FALSE == psIntfAdapter->psAdapter->bEndPointHalted && | |
| FALSE == psIntfAdapter->bSuspended && | |
| FALSE == psIntfAdapter->bPreparingForBusSuspend && | |
| FALSE == psIntfAdapter->psAdapter->StopAllXaction) | |
| { | |
| status = usb_submit_urb(psIntfAdapter->psInterruptUrb, GFP_ATOMIC); | |
| if (status) | |
| { | |
| BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Cannot send int urb %d\n", status); | |
| if(status == -EPIPE) | |
| { | |
| psIntfAdapter->psAdapter->bEndPointHalted = TRUE ; | |
| wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue); | |
| } | |
| } | |
| } | |
| return status; | |
| } | |