⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wlan_tx.c

📁 marvell cf wifi driver source code CF-8385-linux-x86-5.0.4.p0-132-src.rar
💻 C
字号:
/*
 * File : wlan_tx.c 
 */

#include	"include.h"

/*
 * Without threads 
 */
void wlan_process_tx(wlan_private * priv)
{
	wlan_adapter   *Adapter = priv->adapter;
	u32		flags;

	OS_INTERRUPT_SAVE_AREA;	/* Needed for Threadx; Dummy for Linux */

	ENTER();
    
	spin_lock_irqsave(&Adapter->CurrentTxLock, flags);

	if (!Adapter->CurrentTxSkb) {
		spin_unlock_irqrestore(&Adapter->CurrentTxLock, flags);
		LEAVE();
		return;
	}

	spin_unlock_irqrestore(&Adapter->CurrentTxLock, flags);

#ifdef PS_REQUIRED
	if ((Adapter->PSState == PS_STATE_SLEEP)
#ifdef PS_PRESLEEP
		|| (Adapter->PSState == PS_STATE_PRE_SLEEP)
#endif
	) {
		PRINTK1("In PS State %d"
			" - Not sending the packet\n", Adapter->PSState);
		goto done;
	}
#endif

	if(priv->wlan_dev.dnld_sent) {
		PRINTK("wlan_process_tx(): dnld_sent = %d, not sending\n",
						priv->wlan_dev.dnld_sent);
		return;
	}

	if (MrvDrvSend(priv, Adapter->CurrentTxSkb)) {
		if (Adapter->CurrentTxSkb) {
			kfree_skb(Adapter->CurrentTxSkb);
			Adapter->CurrentTxSkb =  NULL;
		}
		priv->stats.tx_dropped++;
		priv->stats.tx_errors++;
	}
	
	OS_INT_DISABLE;
	priv->adapter->HisRegCpy &= ~HIS_TxDnLdRdy;
	OS_INT_RESTORE;
	
#ifdef PS_REQUIRED
done:
#endif
	LEAVE();
}

int wlan_tx_packet(wlan_private * priv, struct sk_buff *skb)
{
	u32		flags;
	wlan_adapter 	*Adapter = priv->adapter;
	int		ret = WLAN_STATUS_SUCCESS;

	ENTER();

	spin_lock_irqsave(&Adapter->CurrentTxLock, flags);

#ifdef WMM
	if(Adapter->wmm.enabled) {
		wmm_map_and_add_skb(priv, skb);
		wake_up_interruptible(&priv->MainThread.waitQ);
	} else
#endif /* WMM */
	if (!Adapter->CurrentTxSkb) {
		Adapter->CurrentTxSkb = skb;
		wake_up_interruptible(&priv->MainThread.waitQ);
	} else {
		ret = WLAN_STATUS_FAILURE;
	}
	
	spin_unlock_irqrestore(&Adapter->CurrentTxLock, flags);

	LEAVE();

	return ret;
}

int wlan_tx_end_packet(wlan_private * priv)
{
	int             rval = WLAN_STATUS_FAILURE;
	PWLAN_OBJECT    iface = &priv->iface;

	ENTER();

	if (!iface->tx_started) {
		PRINTK1("tx not started!\n");
		goto done;
	}

	rval = sbi_host_to_card(priv, MVMS_DAT, iface->tx_buf, 
							iface->tx_pktlen);
	if (!rval) {
		PRINTK1("Data transfer to device ok!\n");
	} else {
		PRINTK("Data transfer to device failed!\n");
	}

done:	
	iface->tx_started = FALSE;
	iface->tx_pktlen = 0;
	iface->tx_pktcnt = 0;

	LEAVE();
	return rval;
}

/*
 * Is called by MrvDrvSend - who can be called either by a thread or
 * directly after a packet is received from the network layer 
 */
int SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
{
	wlan_adapter   *Adapter = priv->adapter;
	int             ixStatus = WLAN_STATUS_SUCCESS;
	u32             TotalBufferLength = 0;
	TxPD		*pLocalTxPD = &Adapter->LocalTxPD;
	u8		*ptr = priv->iface.tx_buf;
	unsigned short 	prot_sn,ping_sn;

	ENTER();

	TXRX_DEBUG_GET_TIME(1);

	if (!skb->len) {
		PRINTK("TX - WLAN buffer is not valid, return FAILURE \n");
		return -1;
	}

	/* need to compare to entire buffer size */
	if (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE) {
		/* TODO: Handle this condition gracefully. */
		PRINTK("Bad skb length %d > %d\n", skb->len, 
					MRVDRV_ETH_TX_PACKET_BUFFER_SIZE);
		kfree_skb((struct sk_buff *) skb);
		Adapter->CurrentTxSkb =  NULL;
		priv->stats.tx_dropped++;
		return -1;
	}

	memset(pLocalTxPD, 0, sizeof(TxPD));

	pLocalTxPD->TxStatus = MRVDRV_TxPD_STATUS_USED;

	pLocalTxPD->TxPacketLength = skb->len;

#ifdef WMM
	if(Adapter->wmm.enabled) {
		/* 
		 * original skb->priority has been overwritten 
		 * by wmm_map_and_add_skb()
		 */
		pLocalTxPD->Priority = (u8)skb->priority;
#ifdef WMM_UAPSD
    if (Adapter->PSState != PS_STATE_FULL_POWER)
    {
			if ((Adapter->CurBssParams.wmm_uapsd_enabled == TRUE) && (Adapter->wmm.qosinfo != 0))
      {
        if (wmm_lists_empty(priv) && (Adapter->sleep_period.period != 0))
        {
          Adapter->wmm.no_more_packet = 1;
          pLocalTxPD->PowerMgmt = MRVDRV_TxPD_POWER_MGMT_LAST_PACKET;
        } 
      }
    }
#endif
	}
#endif /* WMM */

	// Size of TxPd structure;
	pLocalTxPD->TxPacketLocation = sizeof(TxPD);

	// Other TxPD member can be filled in here
	// Auto Mode , 3 retries 
	pLocalTxPD->TxControl = ((Adapter->TxRetryCount & 0x0f) << 12) | 
					data_rate_to_index(Adapter->DataRate);
	// retry_and_rate is no longer used, overrid with TxControl ioctl value
	pLocalTxPD->TxControl = Adapter->PktTxCtrl;

#ifdef	BIG_ENDIAN 
	endian_convert_pLocalTxPD(pLocalTxPD);
#endif	

	memcpy(pLocalTxPD->TxDestAddrHigh, skb->data, MRVDRV_ETH_ADDR_LEN);

	// Start the packet.
	TotalBufferLength = skb->len + sizeof(TxPD);

	ixStatus = wlan_Start_Tx_Packet(priv, (u16) TotalBufferLength);
	TXRX_DEBUG_GET_TIME(2);
	PRINTK1("TX %d bytes: @ %lu\n", TotalBufferLength, 
			os_time_get());
	if (!(ixStatus)) {
		PRINTK("Frame not accepted: interface still "
				"busy after waiting\n");
		return WLAN_STATUS_FAILURE;
	}
	TXRX_DEBUG_GET_TIME(3);
	
	HEXDUMP("TxPD", (u8 *) pLocalTxPD, sizeof(TxPD));

	memcpy(ptr, pLocalTxPD, sizeof(TxPD));
	
	ptr += sizeof(TxPD);
		
	HEXDUMP("Tx Data", (u8 *) skb->data, skb->len);
	memcpy(ptr, skb->data, skb->len);

	TXRX_DEBUG_GET_TIME(4);
	prot_sn = ((unsigned short *)(skb->data))[17];
	ping_sn = ((unsigned short *)(skb->data))[20];
	
	ixStatus = wlan_tx_end_packet(priv);
	
	if (ixStatus) {
		PRINTK("tx_end_packet failed: 0x%X\n",ixStatus);
		 return ixStatus;
	}

	TXRX_DEBUG_GET_TIME(5);

	os_free_tx_packet(priv);
	
	PRINTK1("DONE TX PACKET:\n");

	Adapter->SentFlags = 0;
	priv->stats.tx_packets++;
	priv->stats.tx_bytes += TotalBufferLength;

	LEAVE();
	return WLAN_STATUS_SUCCESS;
}

#ifdef WMM_UAPSD
int SendNullPacket(wlan_private * priv, u8 pwr_mgmt)
{
  TxPD txpd;
  u32 retry_and_rate;
  int r;

  ENTER();

	if (priv->adapter->SurpriseRemoved == TRUE)
    return -1;

	if (priv->adapter->bIsPendingReset == TRUE)
    return -1;

	if (priv->adapter->MediaConnectStatus == WlanMediaStateDisconnected)
    return -1;

  memset(&txpd, 0, sizeof(TxPD));

  retry_and_rate  = (priv->adapter->TxRetryCount & 0x0f) << 12;
  retry_and_rate |= data_rate_to_index(priv->adapter->DataRate);

  txpd.TxControl   = retry_and_rate;
  txpd.PowerMgmt   = pwr_mgmt;
  txpd.TxStatus    = MRVDRV_TxPD_STATUS_USED;
  txpd.TxPacketLocation = sizeof(TxPD);

#ifdef BIG_ENDIAN 
  endian_convert_pLocalTxPD(&txpd);
#endif  

  r = wlan_Start_Tx_Packet(priv, sizeof(TxPD));

  if (r == 0) 
  {
    PRINTK("SendNullPacket failed!\n");
    return WLAN_STATUS_FAILURE;
  }

  memcpy(priv->iface.tx_buf, &txpd, sizeof(TxPD));

  r = wlan_tx_end_packet(priv);
  
  if (r != 0)
  {
    PRINTK("SendNullPacket failed!\n");
    return r;
  }

  LEAVE();
  return WLAN_STATUS_SUCCESS;
}
#endif

int wlan_Start_Tx_Packet(wlan_private * priv, int pktlen)
{
	int             ret;
	PWLAN_OBJECT    iface = &priv->iface;	// TODO Get rid of hwiface

	ENTER();

	PRINTK1("Packet Size=%d\n", pktlen);

	if (pktlen > MAX_WLAN_TX_SIZE) {
		PRINTK1("%d  MAX_WLAN_TX_SIZE\n", pktlen);
		priv->stats.tx_dropped++;
		ret = -1;
		goto done;
	}
#ifndef DUMMY_PACKET
/*
	if (sbi_is_tx_download_ready(priv)) {
		PRINTK("DnLd Not Ready - tx_start_packet\n");
		ret = -1;
		goto done;
	}
*/
#endif
	if (iface->tx_started) {
		PRINTK1("Previous packet under process yet!\n");
		ret = -1;
		goto done;
	}
	
	iface->tx_started = TRUE;
	iface->tx_pktlen = pktlen;
	iface->tx_pktcnt = 0;
	ret = 1;

done:
 	LEAVE();
 	return ret;
}

/*
 * To prepare the packet and send can be called (mostly always) * called
 * from the tx_event_thread 
 */
int MrvDrvSend(wlan_private * priv, struct sk_buff *skb)
{
	u32             ret;
	wlan_adapter   *Adapter = priv->adapter;

	ENTER();

	// Check device removal status
	if (Adapter->SurpriseRemoved == TRUE) {
		PRINTK("ERROR: Device Removed!!!\n");
		ret = WLAN_STATUS_FAILURE;
		goto done;
	}

	if (Adapter->bIsPendingReset == TRUE) {
		PRINTK("ERROR: Reset is Pending!!!\n");
		ret = WLAN_STATUS_FAILURE;
		goto done;
	}

	if (Adapter->MediaConnectStatus == WlanMediaStateDisconnected) {
		PRINTK("ERROR: WlanMediaStateDisconnected!!!\n");
		ret = WLAN_STATUS_FAILURE;
		goto done;
	}

	ret = SendSinglePacket(priv, skb);
	
done:

	LEAVE();
	return ret;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -