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	PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)urb->context;
8	PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter ;
9
10	if (netif_msg_intr(Adapter))
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			{
37				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Got USIM interrupt");
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
117int CreateInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter)
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
146INT StartInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter)
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
170