/**
  * This file contains the handling of TX in wlan driver.
  */
#include <linux/netdevice.h>

#include "hostcmd.h"
#include "radiotap.h"
#include "sbi.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
#include "wext.h"

/**
 *  @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE
 *  units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1)
 *
 *  @param rate    Input rate
 *  @return      Output Rate (0 if invalid)
 */
static u32 convert_radiotap_rate_to_mv(u8 rate)
{
	switch (rate) {
	case 2:		/*   1 Mbps */
		return 0 | (1 << 4);
	case 4:		/*   2 Mbps */
		return 1 | (1 << 4);
	case 11:		/* 5.5 Mbps */
		return 2 | (1 << 4);
	case 22:		/*  11 Mbps */
		return 3 | (1 << 4);
	case 12:		/*   6 Mbps */
		return 4 | (1 << 4);
	case 18:		/*   9 Mbps */
		return 5 | (1 << 4);
	case 24:		/*  12 Mbps */
		return 6 | (1 << 4);
	case 36:		/*  18 Mbps */
		return 7 | (1 << 4);
	case 48:		/*  24 Mbps */
		return 8 | (1 << 4);
	case 72:		/*  36 Mbps */
		return 9 | (1 << 4);
	case 96:		/*  48 Mbps */
		return 10 | (1 << 4);
	case 108:		/*  54 Mbps */
		return 11 | (1 << 4);
	}
	return 0;
}

/**
 *  @brief This function processes a single packet and sends
 *  to IF layer
 *
 *  @param priv    A pointer to wlan_private structure
 *  @param skb     A pointer to skb which includes TX packet
 *  @return 	   0 or -1
 */
static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
{
	wlan_adapter *adapter = priv->adapter;
	int ret = 0;
	struct txpd localtxpd;
	struct txpd *plocaltxpd = &localtxpd;
	u8 *p802x_hdr;
	struct tx_radiotap_hdr *pradiotap_hdr;
	u32 new_rate;
	u8 *ptr = priv->adapter->tmptxbuf;

	ENTER();

	if (priv->adapter->surpriseremoved)
		return -1;

	if ((priv->adapter->debugmode & MRVDRV_DEBUG_TX_PATH) != 0)
		lbs_dbg_hex("TX packet: ", skb->data,
			 min_t(unsigned int, skb->len, 100));

	if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) {
		lbs_pr_debug(1, "Tx error: Bad skb length %d : %zd\n",
		       skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE);
		ret = -1;
		goto done;
	}

	memset(plocaltxpd, 0, sizeof(struct txpd));

	plocaltxpd->tx_packet_length = skb->len;

	/* offset of actual data */
	plocaltxpd->tx_packet_location = sizeof(struct txpd);

	/* TxCtrl set by user or default */
	plocaltxpd->tx_control = adapter->pkttxctrl;

	p802x_hdr = skb->data;
	if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) {

		/* locate radiotap header */
		pradiotap_hdr = (struct tx_radiotap_hdr *)skb->data;

		/* set txpd fields from the radiotap header */
		new_rate = convert_radiotap_rate_to_mv(pradiotap_hdr->rate);
		if (new_rate != 0) {
			/* erase tx_control[4:0] */
			plocaltxpd->tx_control &= ~0x1f;
			/* write new tx_control[4:0] */
			plocaltxpd->tx_control |= new_rate;
		}

		/* skip the radiotap header */
		p802x_hdr += sizeof(struct tx_radiotap_hdr);
		plocaltxpd->tx_packet_length -= sizeof(struct tx_radiotap_hdr);

	}
	/* copy destination address from 802.3 or 802.11 header */
	if (priv->adapter->linkmode == WLAN_LINKMODE_802_11)
		memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr + 4, ETH_ALEN);
	else
		memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr, ETH_ALEN);

	lbs_dbg_hex("txpd", (u8 *) plocaltxpd, sizeof(struct txpd));

	if (IS_MESH_FRAME(skb)) {
		plocaltxpd->tx_control |= TxPD_MESH_FRAME;
	}

	memcpy(ptr, plocaltxpd, sizeof(struct txpd));

	ptr += sizeof(struct txpd);

	lbs_dbg_hex("Tx Data", (u8 *) p802x_hdr, plocaltxpd->tx_packet_length);
	memcpy(ptr, p802x_hdr, plocaltxpd->tx_packet_length);
	ret = libertas_sbi_host_to_card(priv, MVMS_DAT,
			       priv->adapter->tmptxbuf,
			       plocaltxpd->tx_packet_length +
			       sizeof(struct txpd));

	if (ret) {
		lbs_pr_debug(1, "Tx error: libertas_sbi_host_to_card failed: 0x%X\n", ret);
		goto done;
	}

	lbs_pr_debug(1, "SendSinglePacket succeeds\n");

      done:
	if (!ret) {
		priv->stats.tx_packets++;
		priv->stats.tx_bytes += skb->len;
	} else {
		priv->stats.tx_dropped++;
		priv->stats.tx_errors++;
	}

	if (!ret && priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) {
		/* Keep the skb to echo it back once Tx feedback is
		   received from FW */
		skb_orphan(skb);
		/* stop processing outgoing pkts */
		netif_stop_queue(priv->wlan_dev.netdev);
		/* freeze any packets already in our queues */
		priv->adapter->TxLockFlag = 1;
	} else {
		dev_kfree_skb_any(skb);
		priv->adapter->currenttxskb = NULL;
	}

	LEAVE();
	return ret;
}


void libertas_tx_runqueue(wlan_private *priv)
{
	wlan_adapter *adapter = priv->adapter;
	int i;

	spin_lock(&adapter->txqueue_lock);
	for (i = 0; i < adapter->tx_queue_idx; i++) {
		struct sk_buff *skb = adapter->tx_queue_ps[i];
		spin_unlock(&adapter->txqueue_lock);
		SendSinglePacket(priv, skb);
		spin_lock(&adapter->txqueue_lock);
	}
	adapter->tx_queue_idx = 0;
	spin_unlock(&adapter->txqueue_lock);
}

static void wlan_tx_queue(wlan_private *priv, struct sk_buff *skb)
{
	wlan_adapter *adapter = priv->adapter;

	spin_lock(&adapter->txqueue_lock);

	WARN_ON(priv->adapter->tx_queue_idx >= NR_TX_QUEUE);
	adapter->tx_queue_ps[adapter->tx_queue_idx++] = skb;
	if (adapter->tx_queue_idx == NR_TX_QUEUE)
		netif_stop_queue(priv->wlan_dev.netdev);
	else
		netif_start_queue(priv->wlan_dev.netdev);

	spin_unlock(&adapter->txqueue_lock);
}

/**
 *  @brief This function checks the conditions and sends packet to IF
 *  layer if everything is ok.
 *
 *  @param priv    A pointer to wlan_private structure
 *  @return 	   n/a
 */
int libertas_process_tx(wlan_private * priv, struct sk_buff *skb)
{
	int ret = -1;

	ENTER();

	lbs_dbg_hex("TX Data", skb->data, min_t(unsigned int, skb->len, 100));

	if (priv->wlan_dev.dnld_sent) {
		lbs_pr_alert( "TX error: dnld_sent = %d, not sending\n",
		       priv->wlan_dev.dnld_sent);
		goto done;
	}

	if ((priv->adapter->psstate == PS_STATE_SLEEP) ||
	    (priv->adapter->psstate == PS_STATE_PRE_SLEEP)) {
		wlan_tx_queue(priv, skb);
		return ret;
	}

	priv->adapter->currenttxskb = skb;

	ret = SendSinglePacket(priv, skb);
done:
	LEAVE();
	return ret;
}

/**
 *  @brief This function sends to the host the last transmitted packet,
 *  filling the radiotap headers with transmission information.
 *
 *  @param priv     A pointer to wlan_private structure
 *  @param status   A 32 bit value containing transmission status.
 *
 *  @returns void
 */
void libertas_send_tx_feedback(wlan_private * priv)
{
	wlan_adapter *adapter = priv->adapter;
	struct tx_radiotap_hdr *radiotap_hdr;
	u32 status = adapter->eventcause;
	int txfail;
	int try_count;

	if (adapter->radiomode != WLAN_RADIOMODE_RADIOTAP ||
	    adapter->currenttxskb == NULL)
		return;

	radiotap_hdr = (struct tx_radiotap_hdr *)adapter->currenttxskb->data;

	if ((adapter->debugmode & MRVDRV_DEBUG_TX_PATH) != 0)
		lbs_dbg_hex("TX feedback: ", (u8 *) radiotap_hdr,
			min_t(unsigned int, adapter->currenttxskb->len, 100));

	txfail = (status >> 24);

#if 0
	/* The version of roofnet that we've tested does not use this yet
	 * But it may be used in the future.
	 */
	if (txfail)
		radiotap_hdr->flags &= IEEE80211_RADIOTAP_F_TX_FAIL;
#endif
	try_count = (status >> 16) & 0xff;
	radiotap_hdr->data_retries = (try_count) ?
	    (1 + adapter->txretrycount - try_count) : 0;
	libertas_upload_rx_packet(priv, adapter->currenttxskb);
	adapter->currenttxskb = NULL;
	priv->adapter->TxLockFlag = 0;
	if (priv->adapter->connect_status == libertas_connected)
		netif_wake_queue(priv->wlan_dev.netdev);
}
