diff options
Diffstat (limited to 'drivers/staging/bcm/InterfaceIsr.c')
| -rw-r--r-- | drivers/staging/bcm/InterfaceIsr.c | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/drivers/staging/bcm/InterfaceIsr.c b/drivers/staging/bcm/InterfaceIsr.c new file mode 100644 index 00000000000..b9f8a7aa24f --- /dev/null +++ b/drivers/staging/bcm/InterfaceIsr.c @@ -0,0 +1,190 @@ +#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) { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, + DBG_LVL_ALL, "Device has Got Removed."); + return; + } + + if ((Adapter->bPreparingForLowPowerMode && Adapter->bDoSuspend) || + 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; + } + + 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 (!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 (!(psIntfAdapter->psAdapter->device_removed || + psIntfAdapter->psAdapter->bEndPointHalted || + psIntfAdapter->bSuspended || + psIntfAdapter->bPreparingForBusSuspend || + 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 inturb %d\n", status); + if (status == -EPIPE) { + psIntfAdapter->psAdapter->bEndPointHalted = + TRUE; + wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue); + } + } + } + return status; +} + |
