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