#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; }