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