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