INT SendControlPacket(PMINI_ADAPTER Adapter, char *pControlPacket)
{
	PLEADER PLeader = (PLEADER)pControlPacket;

	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx");
	if(!pControlPacket || !Adapter)
	{
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got NULL Control Packet or Adapter");
		return STATUS_FAILURE;
	}
	if((atomic_read( &Adapter->CurrNumFreeTxDesc ) <
		((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1))
    {
    	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET");
        return STATUS_FAILURE;
    }

	
	
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status);
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x",PLeader->Vcid);
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x",PLeader->PLength);
	if(Adapter->device_removed)
		return 0;

	if (netif_msg_pktdata(Adapter))
		print_hex_dump(KERN_DEBUG, PFX "tx control: ", DUMP_PREFIX_NONE,
			       16, 1, pControlPacket, PLeader->PLength + LEADER_SIZE, 0);

	Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
					pControlPacket, (PLeader->PLength + LEADER_SIZE));

	atomic_dec(&Adapter->CurrNumFreeTxDesc);
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<=========");
	return STATUS_SUCCESS;
}
INT SetupNextSend(PMINI_ADAPTER Adapter,  struct sk_buff *Packet, USHORT Vcid)
{
	int		status=0;
	BOOLEAN bHeaderSupressionEnabled = FALSE;
	B_UINT16            uiClassifierRuleID;
	u16	QueueIndex = skb_get_queue_mapping(Packet);
	LEADER Leader={0};

	if(Packet->len > MAX_DEVICE_DESC_SIZE)
	{
		status = STATUS_FAILURE;
		goto errExit;
	}

	
	uiClassifierRuleID = *((UINT32*) (Packet->cb)+SKB_CB_CLASSIFICATION_OFFSET);

	bHeaderSupressionEnabled = Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled
		& Adapter->bPHSEnabled;

	if(Adapter->device_removed)
		{
		status = STATUS_FAILURE;
		goto errExit;
		}

	status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled,
							(UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport);

	if(status != STATUS_SUCCESS)
	{
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n");
		goto errExit;
	}

	Leader.Vcid	= Vcid;

	if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET ))
		Leader.Status = LEADER_STATUS_TCP_ACK;
	else
		Leader.Status = LEADER_STATUS;

	if(Adapter->PackInfo[QueueIndex].bEthCSSupport)
	{
		Leader.PLength = Packet->len;
		if(skb_headroom(Packet) < LEADER_SIZE)
        {
			if((status = skb_cow(Packet,LEADER_SIZE)))
			{
				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n");
				goto errExit;
			}
		}
		skb_push(Packet, LEADER_SIZE);
		memcpy(Packet->data, &Leader, LEADER_SIZE);
	}
	else
	{
		Leader.PLength = Packet->len - ETH_HLEN;
		memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE);
	}

	status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
			Packet->data, (Leader.PLength + LEADER_SIZE));
	if(status)
	{
		++Adapter->dev->stats.tx_errors;
		if (netif_msg_tx_err(Adapter))
			pr_info(PFX "%s: transmit error %d\n", Adapter->dev->name,
				status);
	}
	else
	{
		struct net_device_stats *netstats = &Adapter->dev->stats;
		Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength;

		netstats->tx_bytes += Leader.PLength;
		++netstats->tx_packets;

		Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3;
		Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len);
		Adapter->PackInfo[QueueIndex].uiSentPackets++;
		Adapter->PackInfo[QueueIndex].NumOfPacketsSent++;

		atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount);
		Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength;
	}

	atomic_dec(&Adapter->CurrNumFreeTxDesc);

errExit:

	dev_kfree_skb(Packet);
	return status;
}
Beispiel #3
0
/**
@ingroup tx_functions
This function despatches the IP packets with the given vcid
to the target via the host h/w interface.
@return  zero(success) or -ve value(failure)
*/
INT SetupNextSend(PMINI_ADAPTER Adapter, /**<Logical Adapter*/
					struct sk_buff *Packet, /**<data buffer*/
					USHORT Vcid)			/**<VCID for this packet*/
{
	int		status=0;
#ifdef GDMA_INTERFACE  
	int dontfree = 0;
#endif
	BOOLEAN bHeaderSupressionEnabled = FALSE;
	B_UINT16            uiClassifierRuleID;
	int QueueIndex = NO_OF_QUEUES + 1;
	B_UINT32 time_spent_on_host = 0 ;
	if(!Adapter || !Packet)
	{
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Got NULL Adapter or Packet");
		return -EINVAL;
	}
	if(Packet->len > MAX_DEVICE_DESC_SIZE)
	{
		status = STATUS_FAILURE;
		goto errExit;
	}
	
	/* Get the Classifier Rule ID */
	uiClassifierRuleID = *((UINT32*) (Packet->cb)+SKB_CB_CLASSIFICATION_OFFSET);
	QueueIndex = SearchVcid( Adapter,Vcid);
	if(QueueIndex < NO_OF_QUEUES)
	{
		bHeaderSupressionEnabled = 
			Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled;
		bHeaderSupressionEnabled = 
			bHeaderSupressionEnabled & Adapter->bPHSEnabled;
	}
	if(Adapter->device_removed)
		{
		status = STATUS_FAILURE;
		goto errExit;
		}
	
	status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled, 
							(UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport);

	if(status != STATUS_SUCCESS)
	{
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n");
		goto errExit;
	}

	Leader.Vcid	= Vcid;
	
    if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET ))
	{
        BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending TCP ACK\n");
		Leader.Status = LEADER_STATUS_TCP_ACK;
	}
	else
	{
		Leader.Status = LEADER_STATUS;
	}
	
	if(Adapter->PackInfo[QueueIndex].bEthCSSupport)
	{
		Leader.PLength = Packet->len;
		if(skb_headroom(Packet) < LEADER_SIZE)
        {
			if((status = skb_cow(Packet,LEADER_SIZE)))
			{
				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n");
				goto errExit;
			}
		}
		skb_push(Packet, LEADER_SIZE);
		memcpy(Packet->data, &Leader, LEADER_SIZE);
	}
	
	else	
	{
		Leader.PLength = Packet->len - ETH_HLEN;
		memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE);
	}

	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Packet->len = %d", Packet->len);
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Vcid = %d", Vcid);

#ifndef BCM_SHM_INTERFACE
	status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter, 
			Packet->data, (Leader.PLength + LEADER_SIZE));
#else
	status = tx_pkts_to_firmware(Packet,Packet->len,0);
#endif
	if(status)
	{
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Tx Failed..\n");
	}
	else
	{
		Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength;
		atomic_add(Leader.PLength, &Adapter->GoodTxByteCount);
		atomic_inc(&Adapter->TxTotalPacketCount);
#ifdef GDMA_INTERFACE  
    dontfree = 1;
#endif
	}


	
	time_spent_on_host = jiffies - *((UINT32*) (Packet->cb) + SKB_CB_LATENCY_OFFSET);
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_TIME_SPENT_IN_HOST, DBG_LVL_ALL, "TIME SPENT ON HOST :%#X \n",time_spent_on_host);
	atomic_dec(&Adapter->CurrNumFreeTxDesc);

errExit:

	if(STATUS_SUCCESS == status)
	{
		Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3;
		Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len);
		Adapter->PackInfo[QueueIndex].uiSentPackets++;
		Adapter->PackInfo[QueueIndex].NumOfPacketsSent++;

		atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount);
#ifdef BCM_SHM_INTERFACE
		if(atomic_read(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount) < 0)
		{
			atomic_set(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount, 0);
		}
#endif
		Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength;
	}
	

#ifdef GDMA_INTERFACE  
  if(!dontfree){
  	bcm_kfree_skb(Packet);
  }
#else
  	bcm_kfree_skb(Packet);
#endif  
	return status;
}
Beispiel #4
0
/**
@ingroup ctrl_pkt_functions
This function dispatches control packet to the h/w interface
@return zero(success) or -ve value(failure)
*/
INT SendControlPacket(PMINI_ADAPTER Adapter, /**<Logical Adapter*/
							char *pControlPacket/**<Control Packet*/
							)
{
	PLEADER PLeader = NULL;
	struct timeval tv;
	memset(&tv, 0, sizeof(tv));
		

	
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "========>");

	PLeader=(PLEADER)pControlPacket; 
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx");
	if(!pControlPacket || !Adapter)
	{
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got NULL Control Packet or Adapter");
		return STATUS_FAILURE;
	}
	if((atomic_read( &Adapter->CurrNumFreeTxDesc ) <  
		((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1))
    {
    	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET");
       	if(Adapter->bcm_jiffies == 0)
        {
        	Adapter->bcm_jiffies = jiffies;
            BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "UPDATED TIME(hex): %u", 
				Adapter->bcm_jiffies);
        }
        return STATUS_FAILURE;
    }

	/* Update the netdevice statistics */
	/* Dump Packet  */
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status);
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x",PLeader->Vcid);
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x",PLeader->PLength);
	if(Adapter->device_removed)
		return 0;
#ifndef BCM_SHM_INTERFACE 
	Adapter->interface_transmit(Adapter->pvInterfaceAdapter, 
					pControlPacket, (PLeader->PLength + LEADER_SIZE));
#else
	tx_pkts_to_firmware(pControlPacket,(PLeader->PLength + LEADER_SIZE),1);
		
	if(PLeader->Status==IDLE_MESSAGE)
	{
		if(((CONTROL_MESSAGE*)PLeader)->szData[0] == GO_TO_IDLE_MODE_PAYLOAD &&
		((CONTROL_MESSAGE*)PLeader)->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE)
		{
			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Idle Mode Ack Sent to the Device\n");
        	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Host Entering into Idle Mode\n");
			do_gettimeofday(&tv);
			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "IdleMode Msg sent to f/w at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000);
			if(Adapter->bDoSuspend != TRUE)
			{
				Adapter->IdleMode = TRUE;
				Adapter->bPreparingForLowPowerMode = FALSE ;
			}	
		}
	}
	if((PLeader->Status == LINK_UP_CONTROL_REQ) && 
		((PUCHAR)pControlPacket)[sizeof(LEADER)] == LINK_UP_ACK &&
		((PUCHAR)pControlPacket)[sizeof(LEADER)+1] == 
								LINK_SHUTDOWN_REQ_FROM_FIRMWARE  &&
		((PUCHAR)pControlPacket)[sizeof(LEADER)+2] == SHUTDOWN_ACK_FROM_DRIVER)
	{
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Shut Down ACK Sent and Host entering Shut State \n");
		if(Adapter->bDoSuspend != TRUE)
		{
			Adapter->bShutStatus = TRUE;
			Adapter->bPreparingForLowPowerMode = FALSE;
			Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;
		}
		
	}	
#endif

	((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_packets++;
	((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_bytes+=
			PLeader->PLength;
	atomic_dec(&Adapter->CurrNumFreeTxDesc);
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<=========");
	return STATUS_SUCCESS;
}