]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/bcm/InterfaceIsr.c
Merge branch 'drm-next-3.15-wip' of git://people.freedesktop.org/~deathsimple/linux...
[karo-tx-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) {
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
135 int 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
166 INT 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