1#include "headers.h" 2 3 4static void read_int_callback(struct urb *urb/*, struct pt_regs *regs*/) 5{ 6 int status = urb->status; 7 struct bcm_interface_adapter *psIntfAdapter = 8 (struct bcm_interface_adapter *)urb->context; 9 struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter; 10 11 if (netif_msg_intr(Adapter)) 12 pr_info(PFX "%s: interrupt status %d\n", 13 Adapter->dev->name, status); 14 15 if (Adapter->device_removed) { 16 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, 17 DBG_LVL_ALL, "Device has Got Removed."); 18 return; 19 } 20 21 if ((Adapter->bPreparingForLowPowerMode && Adapter->bDoSuspend) || 22 psIntfAdapter->bSuspended || 23 psIntfAdapter->bPreparingForBusSuspend) { 24 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, 25 DBG_LVL_ALL, 26 "Interrupt call back is called while suspending the device"); 27 return; 28 } 29 30 switch (status) { 31 /* success */ 32 case STATUS_SUCCESS: 33 if (urb->actual_length) { 34 35 if (psIntfAdapter->ulInterruptData[1] & 0xFF) { 36 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, 37 INTF_INIT, DBG_LVL_ALL, 38 "Got USIM interrupt"); 39 } 40 41 if (psIntfAdapter->ulInterruptData[1] & 0xFF00) { 42 atomic_set(&Adapter->CurrNumFreeTxDesc, 43 (psIntfAdapter->ulInterruptData[1] & 44 0xFF00) >> 8); 45 atomic_set(&Adapter->uiMBupdate, TRUE); 46 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, 47 INTF_INIT, DBG_LVL_ALL, 48 "TX mailbox contains %d", 49 atomic_read(&Adapter->CurrNumFreeTxDesc)); 50 } 51 if (psIntfAdapter->ulInterruptData[1] >> 16) { 52 Adapter->CurrNumRecvDescs = 53 (psIntfAdapter->ulInterruptData[1] >> 16); 54 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, 55 INTF_INIT, DBG_LVL_ALL, 56 "RX mailbox contains %d", 57 Adapter->CurrNumRecvDescs); 58 InterfaceRx(psIntfAdapter); 59 } 60 if (Adapter->fw_download_done && 61 !Adapter->downloadDDR && 62 atomic_read(&Adapter->CurrNumFreeTxDesc)) { 63 64 psIntfAdapter->psAdapter->downloadDDR += 1; 65 wake_up(&Adapter->tx_packet_wait_queue); 66 } 67 if (!Adapter->waiting_to_fw_download_done) { 68 Adapter->waiting_to_fw_download_done = TRUE; 69 wake_up(&Adapter->ioctl_fw_dnld_wait_queue); 70 } 71 if (!atomic_read(&Adapter->TxPktAvail)) { 72 atomic_set(&Adapter->TxPktAvail, 1); 73 wake_up(&Adapter->tx_packet_wait_queue); 74 } 75 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, 76 DBG_LVL_ALL, "Firing interrupt in URB"); 77 } 78 break; 79 case -ENOENT: 80 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, 81 DBG_LVL_ALL, "URB has got disconnected...."); 82 return; 83 case -EINPROGRESS: 84 /* 85 * This situation may happened when URBunlink is used. for 86 * detail check usb_unlink_urb documentation. 87 */ 88 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, 89 DBG_LVL_ALL, 90 "Impossibe condition has occurred... something very bad is going on"); 91 break; 92 /* return; */ 93 case -EPIPE: 94 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, 95 DBG_LVL_ALL, 96 "Interrupt IN endPoint has got halted/stalled...need to clear this"); 97 Adapter->bEndPointHalted = TRUE; 98 wake_up(&Adapter->tx_packet_wait_queue); 99 urb->status = STATUS_SUCCESS; 100 return; 101 /* software-driven interface shutdown */ 102 case -ECONNRESET: /* URB got unlinked */ 103 case -ESHUTDOWN: /* hardware gone. this is the serious problem */ 104 /* 105 * Occurs only when something happens with the 106 * host controller device 107 */ 108 case -ENODEV: /* Device got removed */ 109 case -EINVAL: 110 /* 111 * Some thing very bad happened with the URB. No 112 * description is available. 113 */ 114 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, 115 DBG_LVL_ALL, "interrupt urb error %d", status); 116 urb->status = STATUS_SUCCESS; 117 break; 118 /* return; */ 119 default: 120 /* 121 * This is required to check what is the defaults conditions 122 * when it occurs.. 123 */ 124 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, 125 "GOT DEFAULT INTERRUPT URB STATUS :%d..Please Analyze it...", 126 status); 127 break; 128 } 129 130 StartInterruptUrb(psIntfAdapter); 131 132 133} 134 135int CreateInterruptUrb(struct bcm_interface_adapter *psIntfAdapter) 136{ 137 psIntfAdapter->psInterruptUrb = usb_alloc_urb(0, GFP_KERNEL); 138 if (!psIntfAdapter->psInterruptUrb) { 139 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, 140 INTF_INIT, DBG_LVL_ALL, 141 "Cannot allocate interrupt urb"); 142 return -ENOMEM; 143 } 144 psIntfAdapter->psInterruptUrb->transfer_buffer = 145 psIntfAdapter->ulInterruptData; 146 psIntfAdapter->psInterruptUrb->transfer_buffer_length = 147 sizeof(psIntfAdapter->ulInterruptData); 148 149 psIntfAdapter->sIntrIn.int_in_pipe = usb_rcvintpipe(psIntfAdapter->udev, 150 psIntfAdapter->sIntrIn.int_in_endpointAddr); 151 152 usb_fill_int_urb(psIntfAdapter->psInterruptUrb, psIntfAdapter->udev, 153 psIntfAdapter->sIntrIn.int_in_pipe, 154 psIntfAdapter->psInterruptUrb->transfer_buffer, 155 psIntfAdapter->psInterruptUrb->transfer_buffer_length, 156 read_int_callback, psIntfAdapter, 157 psIntfAdapter->sIntrIn.int_in_interval); 158 159 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, INTF_INIT, 160 DBG_LVL_ALL, "Interrupt Interval: %d\n", 161 psIntfAdapter->sIntrIn.int_in_interval); 162 return 0; 163} 164 165 166INT StartInterruptUrb(struct bcm_interface_adapter *psIntfAdapter) 167{ 168 INT status = 0; 169 170 if (!(psIntfAdapter->psAdapter->device_removed || 171 psIntfAdapter->psAdapter->bEndPointHalted || 172 psIntfAdapter->bSuspended || 173 psIntfAdapter->bPreparingForBusSuspend || 174 psIntfAdapter->psAdapter->StopAllXaction)) { 175 status = 176 usb_submit_urb(psIntfAdapter->psInterruptUrb, GFP_ATOMIC); 177 if (status) { 178 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, 179 DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, 180 "Cannot send inturb %d\n", status); 181 if (status == -EPIPE) { 182 psIntfAdapter->psAdapter->bEndPointHalted = 183 TRUE; 184 wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue); 185 } 186 } 187 } 188 return status; 189} 190 191