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