1 #include "headers.h"
2 
SearchVcid(PMINI_ADAPTER Adapter,unsigned short usVcid)3 static int SearchVcid(PMINI_ADAPTER Adapter,unsigned short usVcid)
4 {
5 	int iIndex=0;
6 
7 	for(iIndex=(NO_OF_QUEUES-1);iIndex>=0;iIndex--)
8 		if(Adapter->PackInfo[iIndex].usVCID_Value == usVcid)
9 			return iIndex;
10 	return NO_OF_QUEUES+1;
11 
12 }
13 
14 
15 static PUSB_RCB
GetBulkInRcb(PS_INTERFACE_ADAPTER psIntfAdapter)16 GetBulkInRcb(PS_INTERFACE_ADAPTER psIntfAdapter)
17 {
18 	PUSB_RCB pRcb = NULL;
19 	UINT index = 0;
20 
21 	if((atomic_read(&psIntfAdapter->uNumRcbUsed) < MAXIMUM_USB_RCB) &&
22 		(psIntfAdapter->psAdapter->StopAllXaction == FALSE))
23 	{
24 		index = atomic_read(&psIntfAdapter->uCurrRcb);
25 		pRcb = &psIntfAdapter->asUsbRcb[index];
26 		pRcb->bUsed = TRUE;
27 		pRcb->psIntfAdapter= psIntfAdapter;
28 		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Got Rx desc %d used %d",
29 			index, atomic_read(&psIntfAdapter->uNumRcbUsed));
30 		index = (index + 1) % MAXIMUM_USB_RCB;
31 		atomic_set(&psIntfAdapter->uCurrRcb, index);
32 		atomic_inc(&psIntfAdapter->uNumRcbUsed);
33 	}
34 	return pRcb;
35 }
36 
37 /*this is receive call back - when pkt available for receive (BULK IN- end point)*/
read_bulk_callback(struct urb * urb)38 static void read_bulk_callback(struct urb *urb)
39 {
40 	struct sk_buff *skb = NULL;
41 	BOOLEAN bHeaderSupressionEnabled = FALSE;
42 	int QueueIndex = NO_OF_QUEUES + 1;
43 	UINT uiIndex=0;
44 	int process_done = 1;
45 	//int idleflag = 0 ;
46 	PUSB_RCB pRcb = (PUSB_RCB)urb->context;
47 	PS_INTERFACE_ADAPTER psIntfAdapter = pRcb->psIntfAdapter;
48 	PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter;
49 	PLEADER pLeader = urb->transfer_buffer;
50 
51 	if (unlikely(netif_msg_rx_status(Adapter)))
52 		pr_info(PFX "%s: rx urb status %d length %d\n",
53 			Adapter->dev->name, urb->status, urb->actual_length);
54 
55 	if((Adapter->device_removed == TRUE)  ||
56 		(TRUE == Adapter->bEndPointHalted) ||
57 		(0 == urb->actual_length)
58 		)
59 	{
60 	 	pRcb->bUsed = FALSE;
61  		atomic_dec(&psIntfAdapter->uNumRcbUsed);
62 		return;
63 	}
64 
65 	if(urb->status != STATUS_SUCCESS)
66 	{
67 		if(urb->status == -EPIPE)
68 		{
69 			Adapter->bEndPointHalted = TRUE ;
70 			wake_up(&Adapter->tx_packet_wait_queue);
71 		}
72 		else
73 		{
74 			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,"Rx URB has got cancelled. status :%d", urb->status);
75 		}
76 		pRcb->bUsed = FALSE;
77  		atomic_dec(&psIntfAdapter->uNumRcbUsed);
78 		urb->status = STATUS_SUCCESS ;
79 		return ;
80 	}
81 
82 	if(Adapter->bDoSuspend && (Adapter->bPreparingForLowPowerMode))
83 	{
84 		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,"device is going in low power mode while PMU option selected..hence rx packet should not be process");
85 		return ;
86 	}
87 
88 	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Read back done len %d\n", pLeader->PLength);
89 	if(!pLeader->PLength)
90 	{
91 		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Leader Length 0");
92 		atomic_dec(&psIntfAdapter->uNumRcbUsed);
93 		return;
94 	}
95 	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Leader Status:0x%hX, Length:0x%hX, VCID:0x%hX", pLeader->Status,pLeader->PLength,pLeader->Vcid);
96 	if(MAX_CNTL_PKT_SIZE < pLeader->PLength)
97 	{
98 		if (netif_msg_rx_err(Adapter))
99 			pr_info(PFX "%s: corrupted leader length...%d\n",
100 				Adapter->dev->name, pLeader->PLength);
101 		++Adapter->dev->stats.rx_dropped;
102 		atomic_dec(&psIntfAdapter->uNumRcbUsed);
103 		return;
104 	}
105 
106 	QueueIndex = SearchVcid( Adapter,pLeader->Vcid);
107 	if(QueueIndex < NO_OF_QUEUES)
108 	{
109 		bHeaderSupressionEnabled =
110 			Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled;
111 		bHeaderSupressionEnabled =
112 			bHeaderSupressionEnabled & Adapter->bPHSEnabled;
113 	}
114 
115 	skb = dev_alloc_skb (pLeader->PLength + SKB_RESERVE_PHS_BYTES + SKB_RESERVE_ETHERNET_HEADER);//2   //2 for allignment
116 	if(!skb)
117 	{
118 		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "NO SKBUFF!!! Dropping the Packet");
119 		atomic_dec(&psIntfAdapter->uNumRcbUsed);
120 		return;
121 	}
122     /* If it is a control Packet, then call handle_bcm_packet ()*/
123 	if((ntohs(pLeader->Vcid) == VCID_CONTROL_PACKET) ||
124 	    (!(pLeader->Status >= 0x20  &&  pLeader->Status <= 0x3F)))
125 	{
126 	    BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL, "Received control pkt...");
127 		*(PUSHORT)skb->data = pLeader->Status;
128        	memcpy(skb->data+sizeof(USHORT), urb->transfer_buffer +
129 			(sizeof(LEADER)), pLeader->PLength);
130 		skb->len = pLeader->PLength + sizeof(USHORT);
131 
132 		spin_lock(&Adapter->control_queue_lock);
133 		ENQUEUEPACKET(Adapter->RxControlHead,Adapter->RxControlTail,skb);
134 		spin_unlock(&Adapter->control_queue_lock);
135 
136 		atomic_inc(&Adapter->cntrlpktCnt);
137 		wake_up(&Adapter->process_rx_cntrlpkt);
138 	}
139 	else
140 	{
141 		/*
142 		  * Data Packet, Format a proper Ethernet Header
143         	  * and give it to the stack
144 		  */
145         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt...");
146 		skb_reserve(skb, 2 + SKB_RESERVE_PHS_BYTES);
147 		memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer + sizeof(LEADER), pLeader->PLength);
148 		skb->dev = Adapter->dev;
149 
150 		/* currently skb->len has extra ETH_HLEN bytes in the beginning */
151 		skb_put (skb, pLeader->PLength + ETH_HLEN);
152 		Adapter->PackInfo[QueueIndex].uiTotalRxBytes+=pLeader->PLength;
153 		Adapter->PackInfo[QueueIndex].uiThisPeriodRxBytes+= pLeader->PLength;
154         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt of len :0x%X", pLeader->PLength);
155 
156 		if(netif_running(Adapter->dev))
157 		{
158 			/* Moving ahead by ETH_HLEN to the data ptr as received from FW */
159 			skb_pull(skb, ETH_HLEN);
160 			PHSReceive(Adapter, pLeader->Vcid, skb, &skb->len,
161 					NULL,bHeaderSupressionEnabled);
162 
163 			if(!Adapter->PackInfo[QueueIndex].bEthCSSupport)
164 			{
165 				skb_push(skb, ETH_HLEN);
166 
167 				memcpy(skb->data, skb->dev->dev_addr, 6);
168 				memcpy(skb->data+6, skb->dev->dev_addr, 6);
169 				(*(skb->data+11))++;
170 				*(skb->data+12) = 0x08;
171 				*(skb->data+13) = 0x00;
172 				pLeader->PLength+=ETH_HLEN;
173 			}
174 
175 			skb->protocol = eth_type_trans(skb, Adapter->dev);
176 			process_done = netif_rx(skb);
177 		}
178 		else
179 		{
180 		    BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "i/f not up hance freeing SKB...");
181 			dev_kfree_skb(skb);
182 		}
183 
184 		++Adapter->dev->stats.rx_packets;
185 		Adapter->dev->stats.rx_bytes += pLeader->PLength;
186 
187 		for(uiIndex = 0 ; uiIndex < MIBS_MAX_HIST_ENTRIES ; uiIndex++)
188 		{
189 			if((pLeader->PLength <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1))
190 				&& (pLeader->PLength > MIBS_PKTSIZEHIST_RANGE*(uiIndex)))
191 				Adapter->aRxPktSizeHist[uiIndex]++;
192 		}
193 	}
194  	Adapter->PrevNumRecvDescs++;
195 	pRcb->bUsed = FALSE;
196 	atomic_dec(&psIntfAdapter->uNumRcbUsed);
197 }
198 
ReceiveRcb(PS_INTERFACE_ADAPTER psIntfAdapter,PUSB_RCB pRcb)199 static int ReceiveRcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_RCB pRcb)
200 {
201 	struct urb *urb = pRcb->urb;
202 	int retval = 0;
203 
204 	usb_fill_bulk_urb(urb, psIntfAdapter->udev, usb_rcvbulkpipe(
205 			psIntfAdapter->udev, psIntfAdapter->sBulkIn.bulk_in_endpointAddr),
206 		  	urb->transfer_buffer, BCM_USB_MAX_READ_LENGTH, read_bulk_callback,
207 			pRcb);
208 	if(FALSE == psIntfAdapter->psAdapter->device_removed &&
209 	   FALSE == psIntfAdapter->psAdapter->bEndPointHalted &&
210 	   FALSE == psIntfAdapter->bSuspended &&
211 	   FALSE == psIntfAdapter->bPreparingForBusSuspend)
212 	{
213 		retval = usb_submit_urb(urb, GFP_ATOMIC);
214 		if (retval)
215 		{
216 			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "failed submitting read urb, error %d", retval);
217 			//if this return value is because of pipe halt. need to clear this.
218 			if(retval == -EPIPE)
219 			{
220 				psIntfAdapter->psAdapter->bEndPointHalted = TRUE ;
221 				wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
222 			}
223 
224 		}
225 	}
226 	return retval;
227 }
228 
229 /*
230 Function:				InterfaceRx
231 
232 Description:			This is the hardware specific Function for Receiving
233 						data packet/control packets from the device.
234 
235 Input parameters:		IN PMINI_ADAPTER Adapter   - Miniport Adapter Context
236 
237 
238 
239 Return:				TRUE  - If Rx was successful.
240 					Other - If an error occurred.
241 */
242 
InterfaceRx(PS_INTERFACE_ADAPTER psIntfAdapter)243 BOOLEAN InterfaceRx (PS_INTERFACE_ADAPTER psIntfAdapter)
244 {
245 	USHORT RxDescCount = NUM_RX_DESC - atomic_read(&psIntfAdapter->uNumRcbUsed);
246 	PUSB_RCB pRcb = NULL;
247 
248 //	RxDescCount = psIntfAdapter->psAdapter->CurrNumRecvDescs -
249 //				psIntfAdapter->psAdapter->PrevNumRecvDescs;
250 	while(RxDescCount)
251 	{
252 		pRcb = GetBulkInRcb(psIntfAdapter);
253 		if(pRcb == NULL)
254 		{
255 			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Unable to get Rcb pointer");
256 			return FALSE;
257 		}
258 		//atomic_inc(&psIntfAdapter->uNumRcbUsed);
259 		ReceiveRcb(psIntfAdapter, pRcb);
260 		RxDescCount--;
261     }
262 	return TRUE;
263 }
264 
265